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*  ihevc_chroma_intra_pred_filters.c
22*
23* @brief
24*  Contains function Definition for intra prediction  interpolation filters
25*
26*
27* @author
28*  Ittiam
29*
30* @par List of Functions:
31*  ihevc_intra_pred_chroma_planar()
32*
33*  ihevc_intra_pred_chroma_dc()
34*
35*  ihevc_intra_pred_chroma_horz()
36*
37*  ihevc_intra_pred_chroma_ver()
38*
39*  ihevc_intra_pred_chroma_mode2()
40*
41*  ihevc_intra_pred_chroma_mode_18_34()
42*
43*  ihevc_intra_pred_chroma_mode_3_to_9()
44*
45*  ihevc_intra_pred_chroma_mode_11_to_17()
46*
47*  ihevc_intra_pred_chroma_mode_19_to_25()
48*
49*  ihevc_intra_pred_chroma_mode_27_to_33()
50*
51*  ihevc_intra_pred_chroma_ref_substitution()
52*
53*
54* @remarks
55*  None
56*
57*******************************************************************************
58*/
59
60
61/*****************************************************************************/
62/* File Includes                                                             */
63/*****************************************************************************/
64
65#include "ihevc_typedefs.h"
66#include "ihevc_macros.h"
67#include "ihevc_func_selector.h"
68#include "ihevc_platform_macros.h"
69#include "ihevc_intra_pred.h"
70#include "ihevc_mem_fns.h"
71#include "ihevc_chroma_intra_pred.h"
72#include "ihevc_common_tables.h"
73
74
75/****************************************************************************/
76/* Constant Macros                                                          */
77/****************************************************************************/
78#define MAX_CU_SIZE 64
79#define BIT_DEPTH 8
80#define T32_4NT 128
81#define T16_4NT 64
82#define T16C_4NT 64
83#define T8C_4NT 32
84/****************************************************************************/
85/* Function Macros                                                          */
86/****************************************************************************/
87
88#define GET_BIT(y,x) ((y) & (1 << x)) && (1 << x)
89
90
91/*****************************************************************************/
92/* Function Definition                                                      */
93/*****************************************************************************/
94
95/**
96*******************************************************************************
97*
98* @brief
99*  Reference substitution process for samples unavailable  for prediction
100* Refer to section 8.4.4.2.2
101*
102* @par Description:
103*
104*
105* @param[in] pu1_top_left
106*  UWORD8 pointer to the top-left
107*
108* @param[in] pu1_top
109*  UWORD8 pointer to the top
110*
111* @param[in] pu1_left
112*  UWORD8 pointer to the left
113*
114* @param[in] src_strd
115*  WORD32 Source stride
116*
117* @param[in] nbr_flags
118*  WORD32 neighbor availability flags
119*
120* @param[in] nt
121*  WORD32 transform Block size
122*
123* @param[in] dst_strd
124*  WORD32 Destination stride
125*
126* @returns
127*
128* @remarks
129*  None
130*
131*******************************************************************************
132*/
133
134
135void ihevc_intra_pred_chroma_ref_substitution(UWORD8 *pu1_top_left,
136                                              UWORD8 *pu1_top,
137                                              UWORD8 *pu1_left,
138                                              WORD32 src_strd,
139                                              WORD32 nt,
140                                              WORD32 nbr_flags,
141                                              UWORD8 *pu1_dst,
142                                              WORD32 dst_strd)
143{
144    UWORD8 pu1_ref_u, pu1_ref_v;
145    WORD32 dc_val, i, j;
146    WORD32 total_samples = (4 * nt) + 1;
147    WORD32 get_bits;
148    WORD32 next;
149    WORD32 bot_left, left, top, tp_right, tp_left;
150    WORD32 idx, nbr_id_from_bl, frwd_nbr_flag;
151    WORD32 a_nbr_flag[5];
152    UNUSED(dst_strd);
153    /* Neighbor Flag Structure*/
154    /* WORD32 nbr_flags MSB-->LSB   TOP LEFT | TOP-RIGHT |  TOP   | LEFT    | BOTTOM LEFT*/
155    /*                              (1 bit)     (4 bits)  (4 bits) (4 bits)  (4 bits)  */
156
157    if(nbr_flags == 0)
158    {
159/* If no neighbor flags are present, fill the neighbor samples with DC value */
160        /*dc_val = 1 << (BIT_DEPTH - 1);*/
161        dc_val = 1 << (8 - 1);
162        for(i = 0; i < (2 * total_samples); i++)
163        {
164            pu1_dst[i] = dc_val;
165        }
166    }
167    else
168    {
169        /* Else fill the corresponding samples */
170
171        /* Check for the neighbors availibility */
172        tp_left     = (nbr_flags & 0x10000);
173        tp_right    = (nbr_flags & 0x0f000);
174        top         = (nbr_flags & 0x00f00);
175        left        = (nbr_flags & 0x000f0);
176        bot_left    = (nbr_flags & 0x0000f);
177
178        /* Fill nbrs depending on avalibility */
179        /* Top -Left nbrs  */
180        if(0 != tp_left)
181        {
182            pu1_dst[(4 * nt)] = *pu1_top_left; // U top-left sample
183            pu1_dst[(4 * nt) + 1] = *(pu1_top_left + 1); // V top-left sample
184        }
185        /* Left nbrs  */
186        if(0 != left)
187        {
188            for(i = 0, j = 0; i < (2 * nt); i += 2)
189            {
190                pu1_dst[(4 * nt) - 2 - i] = pu1_left[j * src_strd]; // U left samples
191                pu1_dst[(4 * nt) - 1 - i] = pu1_left[(j * src_strd) + 1]; // V left samples
192                j++;
193            }
194        }
195        /* Bottom - Left nbrs  */
196        if(0 != bot_left)
197        {
198            for(i = (2 * nt), j = nt; i < (4 * nt); i += 2)
199            {
200                pu1_dst[(4 * nt) - 2 - i] = pu1_left[j * src_strd]; // U left samples
201                pu1_dst[(4 * nt) - 1 - i] = pu1_left[(j * src_strd) + 1]; // V left samples
202                j++;
203            }
204        }
205        /* Top nbrs  */
206        if(0 != top)
207        {
208            ihevc_memcpy_mul_8(&pu1_dst[(4 * nt) + 2], pu1_top, 2 * nt);
209            // U-V interleaved Top-top right samples
210        }
211
212        /* Top - Right nbrs  */
213        if(0 != tp_right)
214        {
215            ihevc_memcpy_mul_8(&pu1_dst[(4 * nt) + 2 + 2 * nt], pu1_top + 2 * nt, 2 * nt);
216            // U-V interleaved Top-top right samples
217        }
218
219        if(nt == 4)
220        {
221            /* 1 bit extraction for all the neighboring blocks */
222            tp_left = (nbr_flags & 0x10000) >> 16;
223            bot_left = (nbr_flags & 0x8) >> 3;
224            left = (nbr_flags & 0x80) >> 7;
225            top = (nbr_flags & 0x100) >> 8;
226            tp_right = (nbr_flags & 0x1000) >> 12;
227
228            next = 1;
229            a_nbr_flag[0] = bot_left;
230            a_nbr_flag[1] = left;
231            a_nbr_flag[2] = tp_left;
232            a_nbr_flag[3] = top;
233            a_nbr_flag[4] = tp_right;
234
235            /* If bottom -left is not available, reverse substitution process*/
236            if(bot_left == 0)
237            {
238                /* Check for the 1st available sample from bottom-left*/
239                while(!a_nbr_flag[next])
240                    next++;
241
242                /* If Left, top-left are available*/
243                if(next <= 2)
244                {
245                    UWORD16 *pu2_dst;
246                    idx = (nt * next);
247                    pu2_dst = (UWORD16 *)&pu1_dst[2 * idx];
248                    ihevc_memset_16bit((UWORD16 *)pu1_dst, pu2_dst[0], idx);
249                }
250                else /* If top, top-right are available */
251                {
252                    UWORD16 *pu2_dst;
253                    /* Idx is changed to copy 1 pixel value for top-left ,if top-left is not available*/
254                    idx = (nt * (next - 1)) + 1;
255                    pu2_dst = (UWORD16 *)&pu1_dst[2 * idx];
256                    ihevc_memset_16bit((UWORD16 *)pu1_dst, pu2_dst[0], idx);
257                }
258            }
259
260            if(left == 0)
261            {
262                UWORD16 *pu2_dst = (UWORD16 *)&pu1_dst[(2 * nt) - 2];
263                ihevc_memset_16bit((UWORD16 *)&pu1_dst[(2 * nt)], pu2_dst[0], nt);
264
265
266            }
267            if(tp_left == 0)
268            {
269                pu1_dst[4 * nt] = pu1_dst[(4 * nt) - 2];
270                pu1_dst[(4 * nt) + 1] = pu1_dst[(4 * nt) - 1];
271            }
272            if(top == 0)
273            {
274                UWORD16 *pu2_dst = (UWORD16 *)&pu1_dst[(4 * nt)];
275                ihevc_memset_16bit((UWORD16 *)&pu1_dst[(4 * nt) + 2], pu2_dst[0], nt);
276
277
278            }
279            if(tp_right == 0)
280            {
281                UWORD16 *pu2_dst = (UWORD16 *)&pu1_dst[(6 * nt)];
282                ihevc_memset_16bit((UWORD16 *)&pu1_dst[(6 * nt) + 2], pu2_dst[0], nt);
283
284
285            }
286        }
287        else if(nt == 8)
288        {
289            WORD32 nbr_flags_temp = 0;
290            nbr_flags_temp = ((nbr_flags & 0xC) >> 2) + ((nbr_flags & 0xC0) >> 4)
291                            + ((nbr_flags & 0x300) >> 4)
292                            + ((nbr_flags & 0x3000) >> 6)
293                            + ((nbr_flags & 0x10000) >> 8);
294
295            /* compute trailing zeors based on nbr_flag for substitution process of below left see section .*/
296            /* as each bit in nbr flags corresponds to 8 pels for bot_left, left, top and topright but 1 pel for topleft */
297            {
298                nbr_id_from_bl = look_up_trailing_zeros(nbr_flags_temp & 0XF) * 4; /* for bottom left and left */
299                if(nbr_id_from_bl == 32)
300                    nbr_id_from_bl = 16;
301                if(nbr_id_from_bl == 16)
302                {
303                    /* for top left : 1 pel per nbr bit */
304                    if(!((nbr_flags_temp >> 8) & 0x1))
305                    {
306                        nbr_id_from_bl++;
307                        nbr_id_from_bl += look_up_trailing_zeros((nbr_flags_temp >> 4) & 0xF) * 4; /* top and top right;  8 pels per nbr bit */
308
309                    }
310                }
311                /* Reverse Substitution Process*/
312                if(nbr_id_from_bl)
313                {
314                    /* Replicate the bottom-left and subsequent unavailable pixels with the 1st available pixel above */
315                    pu1_ref_u = pu1_dst[2 * nbr_id_from_bl];
316                    pu1_ref_v = pu1_dst[(2 * nbr_id_from_bl) + 1];
317                    for(i = 2 * (nbr_id_from_bl - 1); i >= 0; i -= 2)
318                    {
319                        pu1_dst[i] = pu1_ref_u;
320                        pu1_dst[i + 1] = pu1_ref_v;
321                    }
322                }
323            }
324
325            /* for the loop of 4*Nt+1 pixels (excluding pixels computed from reverse substitution) */
326            while(nbr_id_from_bl < ((T8C_4NT)+1))
327            {
328                /* To Obtain the next unavailable idx flag after reverse neighbor substitution  */
329                /* Divide by 8 to obtain the original index */
330                frwd_nbr_flag = (nbr_id_from_bl >> 2); /*+ (nbr_id_from_bl & 0x1);*/
331
332                /* The Top-left flag is at the last bit location of nbr_flags*/
333                if(nbr_id_from_bl == (T8C_4NT / 2))
334                {
335                    get_bits = GET_BIT(nbr_flags_temp, 8);
336
337                    /* only pel substitution for TL */
338                    if(!get_bits)
339                    {
340                        pu1_dst[2 * nbr_id_from_bl] = pu1_dst[(2 * nbr_id_from_bl) - 2];
341                        pu1_dst[(2 * nbr_id_from_bl) + 1] = pu1_dst[(2 * nbr_id_from_bl) - 1];
342                    }
343                }
344                else
345                {
346                    get_bits = GET_BIT(nbr_flags_temp, frwd_nbr_flag);
347                    if(!get_bits)
348                    {
349                        UWORD16 *pu2_dst;
350                        /* 8 pel substitution (other than TL) */
351                        pu2_dst = (UWORD16 *)&pu1_dst[(2 * nbr_id_from_bl) - 2];
352                        ihevc_memset_16bit((UWORD16 *)(pu1_dst + (2 * nbr_id_from_bl)), pu2_dst[0], 4);
353                    }
354
355                }
356                nbr_id_from_bl += (nbr_id_from_bl == (T8C_4NT / 2)) ? 1 : 4;
357            }
358
359        }
360        else if(nt == 16)
361        {
362            /* compute trailing ones based on mbr_flag for substitution process of below left see section .*/
363            /* as each bit in nbr flags corresponds to 4 pels for bot_left, left, top and topright but 1 pel for topleft */
364            {
365                nbr_id_from_bl = look_up_trailing_zeros((nbr_flags & 0XFF)) * 4; /* for bottom left and left */
366
367                if(nbr_id_from_bl == 32)
368                {
369                    /* for top left : 1 pel per nbr bit */
370                    if(!((nbr_flags >> 16) & 0x1))
371                    {
372                        /* top left not available */
373                        nbr_id_from_bl++;
374                        /* top and top right;  4 pels per nbr bit */
375                        nbr_id_from_bl += look_up_trailing_zeros((nbr_flags >> 8) & 0xFF) * 4;
376                    }
377                }
378                /* Reverse Substitution Process*/
379                if(nbr_id_from_bl)
380                {
381                    /* Replicate the bottom-left and subsequent unavailable pixels with the 1st available pixel above */
382                    pu1_ref_u = pu1_dst[2 * nbr_id_from_bl];
383                    pu1_ref_v = pu1_dst[2 * nbr_id_from_bl + 1];
384                    for(i = (2 * (nbr_id_from_bl - 1)); i >= 0; i -= 2)
385                    {
386                        pu1_dst[i] = pu1_ref_u;
387                        pu1_dst[i + 1] = pu1_ref_v;
388                    }
389                }
390            }
391
392            /* for the loop of 4*Nt+1 pixels (excluding pixels computed from reverse substitution) */
393            while(nbr_id_from_bl < ((T16C_4NT)+1))
394            {
395                /* To Obtain the next unavailable idx flag after reverse neighbor substitution  */
396                /* Devide by 4 to obtain the original index */
397                frwd_nbr_flag = (nbr_id_from_bl >> 2); /*+ (nbr_id_from_bl & 0x1);*/
398
399                /* The Top-left flag is at the last bit location of nbr_flags*/
400                if(nbr_id_from_bl == (T16C_4NT / 2))
401                {
402                    get_bits = GET_BIT(nbr_flags, 16);
403                    /* only pel substitution for TL */
404                    if(!get_bits)
405                    {
406                        pu1_dst[2 * nbr_id_from_bl] = pu1_dst[(2 * nbr_id_from_bl) - 2];
407                        pu1_dst[(2 * nbr_id_from_bl) + 1] = pu1_dst[(2 * nbr_id_from_bl) - 1];
408                    }
409                }
410                else
411                {
412                    get_bits = GET_BIT(nbr_flags, frwd_nbr_flag);
413                    if(!get_bits)
414                    {
415                        UWORD16 *pu2_dst;
416                        /* 4 pel substitution (other than TL) */
417                        pu2_dst = (UWORD16 *)&pu1_dst[(2 * nbr_id_from_bl) - 2];
418                        ihevc_memset_16bit((UWORD16 *)(pu1_dst + (2 * nbr_id_from_bl)), pu2_dst[0], 4);
419                    }
420
421                }
422                nbr_id_from_bl += (nbr_id_from_bl == (T16C_4NT / 2)) ? 1 : 4;
423            }
424        }
425    }
426}
427
428
429/**
430*******************************************************************************
431*
432* @brief
433*  Planar Intraprediction with reference neighboring samples location
434* pointed by 'pu1_ref' to the TU block location  pointed by 'pu1_dst'  Refer
435* to section 8.4.4.2.4 in the standard
436*
437* @par Description:
438*
439*
440* @param[in] pu1_src
441*  UWORD8 pointer to the source
442*
443* @param[in] pu1_dst
444*  UWORD8 pointer to the destination
445*
446* @param[in] src_strd
447*  integer source stride
448*
449* @param[in] dst_strd
450*  integer destination stride
451*
452* @param[in] nt
453*  integer Transform Block size
454*
455* @param[in] mode
456*  integer intraprediction mode
457*
458* @returns
459*
460* @remarks
461*  None
462*
463*******************************************************************************
464*/
465
466
467void ihevc_intra_pred_chroma_planar(UWORD8 *pu1_ref,
468                                    WORD32 src_strd,
469                                    UWORD8 *pu1_dst,
470                                    WORD32 dst_strd,
471                                    WORD32 nt,
472                                    WORD32 mode)
473{
474
475    WORD32 row, col;
476    WORD32 log2nt = 5;
477    WORD32 two_nt, three_nt;
478    UNUSED(src_strd);
479    UNUSED(mode);
480    switch(nt)
481    {
482        case 16:
483            log2nt = 4;
484            break;
485        case 8:
486            log2nt = 3;
487            break;
488        case 4:
489            log2nt = 2;
490            break;
491        default:
492            break;
493    }
494    two_nt = 2 * nt;
495    three_nt = 3 * nt;
496    /* Planar filtering */
497    for(row = 0; row < nt; row++)
498    {
499        for(col = 0; col < (2 * nt); col += 2)
500        {
501            pu1_dst[row * dst_strd + col] = ((nt - 1 - col / 2)
502                            * pu1_ref[2 * (two_nt - 1 - row)]
503                            + (col / 2 + 1) * pu1_ref[2 * (three_nt + 1)]
504                            + (nt - 1 - row) * pu1_ref[2 * (two_nt + 1) + col]
505                            + (row + 1) * pu1_ref[2 * (nt - 1)] + nt) >> (log2nt + 1);
506
507            pu1_dst[row * dst_strd + col + 1] = ((nt - 1 - col / 2)
508                            * pu1_ref[2 * (two_nt - 1 - row) + 1]
509                            + (col / 2 + 1) * pu1_ref[2 * (three_nt + 1) + 1]
510                            + (nt - 1 - row) * pu1_ref[2 * (two_nt + 1) + col + 1]
511                            + (row + 1) * pu1_ref[2 * (nt - 1) + 1] + nt) >> (log2nt + 1);
512        }
513    }
514}
515
516
517/**
518*******************************************************************************
519*
520* @brief
521*  Intraprediction for DC mode with reference neighboring  samples location
522* pointed by 'pu1_ref' to the TU block  location pointed by 'pu1_dst'  Refer
523* to section 8.4.4.2.5 in the standard
524*
525* @par Description:
526*
527*
528* @param[in] pu1_src
529*  UWORD8 pointer to the source
530*
531* @param[in] pu1_dst
532*  UWORD8 pointer to the destination
533*
534* @param[in] src_strd
535*  integer source stride
536*
537* @param[in] dst_strd
538*  integer destination stride
539*
540* @param[in] nt
541*  integer Transform Block size (Chroma)
542*
543* @param[in] mode
544*  integer intraprediction mode
545*
546* @returns
547*
548* @remarks
549*  None
550*
551*******************************************************************************
552*/
553
554
555void ihevc_intra_pred_chroma_dc(UWORD8 *pu1_ref,
556                                WORD32 src_strd,
557                                UWORD8 *pu1_dst,
558                                WORD32 dst_strd,
559                                WORD32 nt,
560                                WORD32 mode)
561{
562
563    WORD32 acc_dc_u, acc_dc_v;
564    WORD32 dc_val_u, dc_val_v;
565    WORD32 i;
566    WORD32 row, col;
567    WORD32 log2nt = 5;
568    UNUSED(mode);
569    UNUSED(src_strd);
570    switch(nt)
571    {
572        case 32:
573            log2nt = 5;
574            break;
575        case 16:
576            log2nt = 4;
577            break;
578        case 8:
579            log2nt = 3;
580            break;
581        case 4:
582            log2nt = 2;
583            break;
584        default:
585            break;
586    }
587
588
589    acc_dc_u = 0;
590    acc_dc_v = 0;
591    /* Calculate DC value for the transform block */
592    for(i = (2 * nt); i < (4 * nt); i += 2)
593    {
594        acc_dc_u += pu1_ref[i];
595        acc_dc_v += pu1_ref[i + 1];
596    }
597    for(i = ((4 * nt) + 2); i < ((6 * nt) + 2); i += 2)
598    {
599        acc_dc_u += pu1_ref[i];
600        acc_dc_v += pu1_ref[i + 1];
601    }
602
603
604    dc_val_u = (acc_dc_u + nt) >> (log2nt + 1);
605    dc_val_v = (acc_dc_v + nt) >> (log2nt + 1);
606
607
608    /* Fill the remaining rows with DC value*/
609    for(row = 0; row < nt; row++)
610    {
611        for(col = 0; col < (2 * nt); col += 2)
612        {
613            pu1_dst[(row * dst_strd) + col] = dc_val_u;
614            pu1_dst[(row * dst_strd) + col + 1] = dc_val_v;
615        }
616    }
617
618}
619
620
621/**
622*******************************************************************************
623*
624* @brief
625*  Horizontal intraprediction(mode 10) with reference  samples location
626* pointed by 'pu1_ref' to the TU block  location pointed by 'pu1_dst'  Refer
627* to section 8.4.4.2.6 in the standard (Special case)
628*
629* @par Description:
630*
631*
632* @param[in] pu1_src
633*  UWORD8 pointer to the source
634*
635* @param[in] pu1_dst
636*  UWORD8 pointer to the destination
637*
638* @param[in] src_strd
639*  integer source stride
640*
641* @param[in] dst_strd
642*  integer destination stride
643*
644* @param[in] nt
645*  integer Transform Block size
646*
647* @param[in] mode
648*  integer intraprediction mode
649*
650* @returns
651*
652* @remarks
653*  None
654*
655*******************************************************************************
656*/
657
658
659void ihevc_intra_pred_chroma_horz(UWORD8 *pu1_ref,
660                                  WORD32 src_strd,
661                                  UWORD8 *pu1_dst,
662                                  WORD32 dst_strd,
663                                  WORD32 nt,
664                                  WORD32 mode)
665{
666
667    WORD32 row, col;
668    UNUSED(mode);
669    UNUSED(src_strd);
670    /* Replication to next rows*/
671    for(row = 0; row < nt; row++)
672    {
673        for(col = 0; col < (2 * nt); col += 2)
674        {
675            pu1_dst[(row * dst_strd) + col] = pu1_ref[(4 * nt) - 2 - 2 * row];
676            pu1_dst[(row * dst_strd) + col + 1] = pu1_ref[(4 * nt) - 1 - 2 * row];
677        }
678    }
679}
680
681
682
683/**
684*******************************************************************************
685*
686* @brief
687*  Horizontal intraprediction with reference neighboring  samples location
688* pointed by 'pu1_ref' to the TU block  location pointed by 'pu1_dst'  Refer
689* to section 8.4.4.2.6 in the standard (Special case)
690*
691* @par Description:
692*
693*
694* @param[in] pu1_src
695*  UWORD8 pointer to the source
696*
697* @param[in] pu1_dst
698*  UWORD8 pointer to the destination
699*
700* @param[in] src_strd
701*  integer source stride
702*
703* @param[in] dst_strd
704*  integer destination stride
705*
706* @param[in] nt
707*  integer Transform Block size
708*
709* @param[in] mode
710*  integer intraprediction mode
711*
712* @returns
713*
714* @remarks
715*  None
716*
717*******************************************************************************
718*/
719
720
721void ihevc_intra_pred_chroma_ver(UWORD8 *pu1_ref,
722                                 WORD32 src_strd,
723                                 UWORD8 *pu1_dst,
724                                 WORD32 dst_strd,
725                                 WORD32 nt,
726                                 WORD32 mode)
727{
728    WORD32 row, col;
729    UNUSED(mode);
730    UNUSED(src_strd);
731    /* Replication to next columns*/
732    for(row = 0; row < nt; row++)
733    {
734        for(col = 0; col < (2 * nt); col += 2)
735        {
736            pu1_dst[(row * dst_strd) + col] = pu1_ref[(4 * nt) + 2 + col];
737            pu1_dst[(row * dst_strd) + col + 1] = pu1_ref[(4 * nt) + 3 + col];
738        }
739    }
740}
741
742
743/**
744*******************************************************************************
745*
746* @brief
747*  Intraprediction for mode 2 (sw angle) with reference  neighboring samples
748* location pointed by 'pu1_ref' to the  TU block location pointed by
749* 'pu1_dst'  Refer to section 8.4.4.2.6 in the standard
750*
751* @par Description:
752*
753*
754* @param[in] pu1_src
755*  UWORD8 pointer to the source
756*
757* @param[in] pu1_dst
758*  UWORD8 pointer to the destination
759*
760* @param[in] src_strd
761*  integer source stride
762*
763* @param[in] dst_strd
764*  integer destination stride
765*
766* @param[in] nt
767*  integer Transform Block size
768*
769* @param[in] mode
770*  integer intraprediction mode
771*
772* @returns
773*
774* @remarks
775*  None
776*
777*******************************************************************************
778*/
779
780
781void ihevc_intra_pred_chroma_mode2(UWORD8 *pu1_ref,
782                                   WORD32 src_strd,
783                                   UWORD8 *pu1_dst,
784                                   WORD32 dst_strd,
785                                   WORD32 nt,
786                                   WORD32 mode)
787{
788    WORD32 row, col;
789
790    WORD32 intra_pred_ang = 32;
791    WORD32 idx_u, idx_v;
792    UNUSED(src_strd);
793    UNUSED(mode);
794    /* For the angle 45, replication is done from the corresponding angle */
795    /* intra_pred_ang = tan(angle) in q5 format */
796    for(col = 0; col < (2 * nt); col += 2)
797    {
798        idx_u = ((col + 1) * intra_pred_ang) >> 5; /* Use idx++ */
799        idx_v = (((col + 1) + 1) * intra_pred_ang) >> 5; /* Use idx++ */
800        for(row = 0; row < nt; row++)
801        {
802            pu1_dst[col + (row * dst_strd)] = pu1_ref[(4 * nt) - 2 * row - idx_u - 3];
803            pu1_dst[(col + 1) + (row * dst_strd)] = pu1_ref[(4 * nt) - 2 * row - idx_v - 1];
804        }
805    }
806
807}
808
809
810/**
811*******************************************************************************
812*
813* @brief
814*  Intraprediction for mode 34 (ne angle) and  mode 18 (nw angle) with
815* reference  neighboring samples location pointed by 'pu1_ref' to the  TU
816* block location pointed by 'pu1_dst'
817*
818* @par Description:
819*
820*
821* @param[in] pu1_src
822*  UWORD8 pointer to the source
823*
824* @param[in] pu1_dst
825*  UWORD8 pointer to the destination
826*
827* @param[in] src_strd
828*  integer source stride
829*
830* @param[in] dst_strd
831*  integer destination stride
832*
833* @param[in] nt
834*  integer Transform Block size
835*
836* @param[in] mode
837*  integer intraprediction mode
838*
839* @returns
840*
841* @remarks
842*  None
843*
844*******************************************************************************
845*/
846
847
848void ihevc_intra_pred_chroma_mode_18_34(UWORD8 *pu1_ref,
849                                        WORD32 src_strd,
850                                        UWORD8 *pu1_dst,
851                                        WORD32 dst_strd,
852                                        WORD32 nt,
853                                        WORD32 mode)
854{
855    WORD32 row, col;
856    WORD32 intra_pred_ang;
857    WORD32 idx = 0;
858    UNUSED(src_strd);
859    intra_pred_ang = 32; /*Default value*/
860    /* For mode 18, angle is -45degree */
861    if(mode == 18)
862        intra_pred_ang = -32;
863    /* For mode 34, angle is 45degree */
864    else if(mode == 34)
865        intra_pred_ang = 32;
866    /* For the angle 45 and -45, replication is done from the corresponding angle */
867    /* No interpolation is done for 45 degree*/
868    for(row = 0; row < nt; row++)
869    {
870        idx = ((row + 1) * intra_pred_ang) >> 5;
871
872        for(col = 0; col < (2 * nt); col += 2)
873        {
874            pu1_dst[col + (row * dst_strd)] = pu1_ref[(4 * nt) + col + 2 * idx + 2];
875            pu1_dst[(col + 1) + (row * dst_strd)] = pu1_ref[(4 * nt) + (col + 1) + 2 * idx + 2];
876        }
877
878    }
879
880}
881
882
883/**
884*******************************************************************************
885*
886* @brief
887*  Intraprediction for mode 3 to 9  (positive angle, horizontal mode ) with
888* reference  neighboring samples location pointed by 'pu1_ref' to the  TU
889* block location pointed by 'pu1_dst'
890*
891* @par Description:
892*
893*
894* @param[in] pu1_src
895*  UWORD8 pointer to the source
896*
897* @param[in] pu1_dst
898*  UWORD8 pointer to the destination
899*
900* @param[in] src_strd
901*  integer source stride
902*
903* @param[in] dst_strd
904*  integer destination stride
905*
906* @param[in] nt
907*  integer Transform Block size
908*
909* @param[in] mode
910*  integer intraprediction mode
911*
912* @returns
913*
914* @remarks
915*  None
916*
917*******************************************************************************
918*/
919
920
921void ihevc_intra_pred_chroma_mode_3_to_9(UWORD8 *pu1_ref,
922                                         WORD32 src_strd,
923                                         UWORD8 *pu1_dst,
924                                         WORD32 dst_strd,
925                                         WORD32 nt,
926                                         WORD32 mode)
927{
928    WORD32 row, col;
929
930    WORD32 intra_pred_ang;
931    WORD32 idx_u, ref_main_idx_u;
932    WORD32 idx_v, ref_main_idx_v;
933    WORD32 pos_u, fract_u;
934    WORD32 pos_v, fract_v;
935    UNUSED(src_strd);
936    /* Intra Pred Angle according to the mode */
937    intra_pred_ang = gai4_ihevc_ang_table[mode];
938
939    /* For the angles other then 45 degree, interpolation btw 2 neighboring */
940    /* samples dependent on distance to obtain destination sample */
941
942    for(col = 0; col < (2 * nt); col += 2)
943    {
944        pos_u = ((col / 2 + 1) * intra_pred_ang);
945        pos_v = ((col / 2 + 1) * intra_pred_ang);
946
947        idx_u = pos_u >> 5;
948        fract_u = pos_u & (31);
949
950        idx_v = pos_v >> 5;
951        fract_v = pos_v & (31);
952        // Do linear filtering
953        for(row = 0; row < nt; row++)
954        {
955            ref_main_idx_u = (4 * nt) - 2 * row - 2 * idx_u - 2;
956            ref_main_idx_v = (4 * nt) - 2 * row - 2 * idx_v - 1;
957
958            pu1_dst[col + (row * dst_strd)] = (((32 - fract_u)
959                            * pu1_ref[ref_main_idx_u]
960                            + fract_u * pu1_ref[ref_main_idx_u - 2] + 16) >> 5);
961
962            pu1_dst[(col + 1) + (row * dst_strd)] = (((32 - fract_v)
963                            * pu1_ref[ref_main_idx_v]
964                            + fract_v * pu1_ref[ref_main_idx_v - 2] + 16) >> 5);
965        }
966
967    }
968
969}
970
971
972/**
973*******************************************************************************
974*
975* @brief
976*  Intraprediction for mode 11 to 17  (negative angle, horizontal mode )
977* with reference  neighboring samples location pointed by 'pu1_ref' to the
978* TU block location pointed by 'pu1_dst'
979*
980* @par Description:
981*
982*
983* @param[in] pu1_src
984*  UWORD8 pointer to the source
985*
986* @param[in] pu1_dst
987*  UWORD8 pointer to the destination
988*
989* @param[in] src_strd
990*  integer source stride
991*
992* @param[in] dst_strd
993*  integer destination stride
994*
995* @param[in] nt
996*  integer Transform Block size
997*
998* @param[in] mode
999*  integer intraprediction mode
1000*
1001* @returns
1002*
1003* @remarks
1004*  None
1005*
1006*******************************************************************************
1007*/
1008
1009
1010void ihevc_intra_pred_chroma_mode_11_to_17(UWORD8 *pu1_ref,
1011                                           WORD32 src_strd,
1012                                           UWORD8 *pu1_dst,
1013                                           WORD32 dst_strd,
1014                                           WORD32 nt,
1015                                           WORD32 mode)
1016{
1017    /* This function and ihevc_intra_pred_CHROMA_mode_19_to_25 are same except*/
1018    /* for ref main & side samples assignment,can be combined for */
1019    /* optimzation*/
1020
1021    WORD32 row, col, k;
1022    WORD32 intra_pred_ang, inv_ang, inv_ang_sum;
1023    WORD32 idx_u, idx_v, ref_main_idx_u, ref_main_idx_v, ref_idx;
1024    WORD32 pos_u, pos_v, fract_u, fract_v;
1025
1026    UWORD8 ref_temp[2 * MAX_CU_SIZE + 2];
1027    UWORD8 *ref_main;
1028    UNUSED(src_strd);
1029    inv_ang_sum = 128;
1030
1031    intra_pred_ang = gai4_ihevc_ang_table[mode];
1032
1033    inv_ang = gai4_ihevc_inv_ang_table[mode - 11];
1034    /* Intermediate reference samples for negative angle modes */
1035    /* This have to be removed during optimization*/
1036
1037    /* For horizontal modes, (ref main = ref left) (ref side = ref above) */
1038
1039
1040    ref_main = ref_temp + 2 * nt;
1041    for(k = 0; k < (2 * (nt + 1)); k += 2)
1042    {
1043        ref_temp[k + (2 * (nt - 1))] = pu1_ref[(4 * nt) - k];
1044        ref_temp[k + 1 + (2 * (nt - 1))] = pu1_ref[(4 * nt) - k + 1];
1045    }
1046
1047    ref_main = ref_temp + (2 * (nt - 1));
1048    ref_idx = (nt * intra_pred_ang) >> 5;
1049
1050    /* SIMD Optimization can be done using look-up table for the loop */
1051    /* For negative angled derive the main reference samples from side */
1052    /*  reference samples refer to section 8.4.4.2.6 */
1053    for(k = -2; k > (2 * ref_idx); k -= 2)
1054    {
1055        inv_ang_sum += inv_ang;
1056        ref_main[k] = pu1_ref[(4 * nt) + ((inv_ang_sum >> 8) << 1)];
1057        ref_main[k + 1] = pu1_ref[((4 * nt) + 1) + ((inv_ang_sum >> 8) << 1)];
1058    }
1059
1060    /* For the angles other then 45 degree, interpolation btw 2 neighboring */
1061    /* samples dependent on distance to obtain destination sample */
1062    for(col = 0; col < (2 * nt); col += 2)
1063    {
1064        pos_u = ((col / 2 + 1) * intra_pred_ang);
1065        pos_v = ((col / 2 + 1) * intra_pred_ang);
1066        idx_u = pos_u >> 5;
1067        idx_v = pos_v >> 5;
1068        fract_u = pos_u & (31);
1069        fract_v = pos_v & (31);
1070
1071        // Do linear filtering
1072        for(row = 0; row < nt; row++)
1073        {
1074            ref_main_idx_u = 2 * (row + idx_u + 1);
1075            ref_main_idx_v = 2 * (row + idx_v + 1) + 1;
1076
1077            pu1_dst[col + (dst_strd * row)] = (UWORD8)(((32 - fract_u)
1078                            * ref_main[ref_main_idx_u]
1079                            + fract_u * ref_main[ref_main_idx_u + 2] + 16) >> 5);
1080            pu1_dst[(col + 1) + (dst_strd * row)] = (UWORD8)(((32 - fract_v)
1081                            * ref_main[ref_main_idx_v]
1082                            + fract_v * ref_main[ref_main_idx_v + 2] + 16) >> 5);
1083
1084        }
1085
1086    }
1087
1088}
1089
1090
1091
1092/**
1093*******************************************************************************
1094*
1095* @brief
1096*  Intraprediction for mode 19 to 25  (negative angle, vertical mode ) with
1097* reference  neighboring samples location pointed by 'pu1_ref' to the  TU
1098* block location pointed by 'pu1_dst'
1099*
1100* @par Description:
1101*
1102*
1103* @param[in] pu1_src
1104*  UWORD8 pointer to the source
1105*
1106* @param[in] pu1_dst
1107*  UWORD8 pointer to the destination
1108*
1109* @param[in] src_strd
1110*  integer source stride
1111*
1112* @param[in] dst_strd
1113*  integer destination stride
1114*
1115* @param[in] nt
1116*  integer Transform Block size
1117*
1118* @param[in] mode
1119*  integer intraprediction mode
1120*
1121* @returns
1122*
1123* @remarks
1124*  None
1125*
1126*******************************************************************************
1127*/
1128
1129
1130void ihevc_intra_pred_chroma_mode_19_to_25(UWORD8 *pu1_ref,
1131                                           WORD32 src_strd,
1132                                           UWORD8 *pu1_dst,
1133                                           WORD32 dst_strd,
1134                                           WORD32 nt,
1135                                           WORD32 mode)
1136{
1137
1138    WORD32 row, col, k;
1139    WORD32 intra_pred_ang, idx;
1140    WORD32 inv_ang, inv_ang_sum, pos, fract;
1141    WORD32 ref_main_idx_u, ref_main_idx_v, ref_idx;
1142    UWORD8 ref_temp[(2 * MAX_CU_SIZE) + 2];
1143    UWORD8 *ref_main;
1144    UNUSED(src_strd);
1145
1146
1147    intra_pred_ang = gai4_ihevc_ang_table_chroma[mode];
1148    inv_ang = gai4_ihevc_inv_ang_table_chroma[mode - 12];
1149
1150    /* Intermediate reference samples for negative angle modes */
1151    /* This have to be removed during optimization*/
1152    /* For horizontal modes, (ref main = ref above) (ref side = ref left) */
1153    ref_main = ref_temp + 2 * nt;
1154    for(k = 0; k < (2 * (nt + 1)); k += 2)
1155    {
1156        ref_temp[k + (2 * (nt - 1))] = pu1_ref[(4 * nt) + k];
1157        ref_temp[k + 1 + (2 * (nt - 1))] = pu1_ref[(4 * nt) + k + 1];
1158    }
1159
1160
1161    ref_idx = (nt * intra_pred_ang) >> 5;
1162    inv_ang_sum = 128;
1163    ref_main = ref_temp + (2 * (nt - 1));
1164    /* SIMD Optimization can be done using look-up table for the loop */
1165    /* For negative angled derive the main reference samples from side */
1166    /*  reference samples refer to section 8.4.4.2.6 */
1167    for(k = -2; k > (2 * ref_idx); k -= 2)
1168    {
1169        inv_ang_sum += inv_ang;
1170        ref_main[k] = pu1_ref[(4 * nt) - (inv_ang_sum >> 8) * 2];
1171        ref_main[k + 1] = pu1_ref[((4 * nt) + 1) - (inv_ang_sum >> 8) * 2];
1172    }
1173
1174    for(row = 0; row < nt; row++)
1175    {
1176        pos = ((row + 1) * intra_pred_ang);
1177        idx = pos >> 5;
1178        fract = pos & (31);
1179
1180        // Do linear filtering
1181        for(col = 0; col < (2 * nt); col += 2)
1182        {
1183            ref_main_idx_u = col + 2 * idx + 2;
1184            ref_main_idx_v = (col + 1) + 2 * idx + 2;
1185            pu1_dst[(row * dst_strd) + col] = (UWORD8)(((32 - fract)
1186                            * ref_main[ref_main_idx_u]
1187                            + fract * ref_main[ref_main_idx_u + 2] + 16) >> 5);
1188            pu1_dst[(row * dst_strd) + (col + 1)] = (UWORD8)(((32 - fract)
1189                            * ref_main[ref_main_idx_v]
1190                            + fract * ref_main[ref_main_idx_v + 2] + 16) >> 5);
1191
1192        }
1193
1194    }
1195
1196}
1197
1198
1199
1200/**
1201*******************************************************************************
1202*
1203* @brief
1204*  Intraprediction for mode 27 to 33  (positive angle, vertical mode ) with
1205* reference  neighboring samples location pointed by 'pu1_ref' to the  TU
1206* block location pointed by 'pu1_dst'
1207*
1208* @par Description:
1209*
1210*
1211* @param[in] pu1_src
1212*  UWORD8 pointer to the source
1213*
1214* @param[in] pu1_dst
1215*  UWORD8 pointer to the destination
1216*
1217* @param[in] src_strd
1218*  integer source stride
1219*
1220* @param[in] dst_strd
1221*  integer destination stride
1222*
1223* @param[in] nt
1224*  integer Transform Block size
1225*
1226* @param[in] mode
1227*  integer intraprediction mode
1228*
1229* @returns
1230*
1231* @remarks
1232*  None
1233*
1234*******************************************************************************
1235*/
1236
1237
1238void ihevc_intra_pred_chroma_mode_27_to_33(UWORD8 *pu1_ref,
1239                                           WORD32 src_strd,
1240                                           UWORD8 *pu1_dst,
1241                                           WORD32 dst_strd,
1242                                           WORD32 nt,
1243                                           WORD32 mode)
1244{
1245    WORD32 row, col;
1246    WORD32 pos, fract;
1247    WORD32 intra_pred_ang;
1248    WORD32 idx, ref_main_idx_u, ref_main_idx_v;
1249    UNUSED(src_strd);
1250
1251
1252    intra_pred_ang = gai4_ihevc_ang_table_chroma[mode];
1253
1254    for(row = 0; row < nt; row++)
1255    {
1256        pos = ((row + 1) * intra_pred_ang);
1257        idx = pos >> 5;
1258        fract = pos & (31);
1259
1260
1261        // Do linear filtering
1262        for(col = 0; col < (2 * nt); col += 2)
1263        {
1264            ref_main_idx_u = (4 * nt) + col + 2 * idx + 2;
1265            ref_main_idx_v = (4 * nt) + (col + 1) + 2 * idx + 2;
1266            pu1_dst[col + (row * dst_strd)] = (((32 - fract)
1267                            * pu1_ref[ref_main_idx_u]
1268                            + fract * pu1_ref[ref_main_idx_u + 2] + 16) >> 5);
1269            pu1_dst[(col + 1) + (row * dst_strd)] = (((32 - fract)
1270                            * pu1_ref[ref_main_idx_v]
1271                            + fract * pu1_ref[ref_main_idx_v + 2] + 16) >> 5);
1272
1273        }
1274    }
1275
1276}
1277
1278