Home | History | Annotate | Download | only in encoder
      1 /******************************************************************************
      2  *
      3  * Copyright (C) 2015 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 
     21 /**
     22 *******************************************************************************
     23 * @file
     24 *  ih264e_fmt_conv.c
     25 *
     26 * @brief
     27 *  Contains functions for format conversion or frame copy of output buffer
     28 *
     29 * @author
     30 *  ittiam
     31 *
     32 * @par List of Functions:
     33 *  - ih264e_fmt_conv_420sp_to_rgb565()
     34 *  - ih264e_fmt_conv_420sp_to_rgba8888()
     35 *  - ih264e_fmt_conv_420sp_to_420sp()
     36 *  - ih264e_fmt_conv_420sp_to_420sp_swap_uv()
     37 *  - ih264e_fmt_conv_420sp_to_420p()
     38 *  - ih264e_fmt_conv_420p_to_420sp()
     39 *  - ih264e_fmt_conv_422i_to_420sp()
     40 *  - ih264e_fmt_conv()
     41 *
     42 * @remarks
     43 *  None
     44 *
     45 *******************************************************************************
     46 */
     47 
     48 /*****************************************************************************/
     49 /* File Includes                                                             */
     50 /*****************************************************************************/
     51 
     52 /* System Include files */
     53 #include <stdio.h>
     54 #include <stddef.h>
     55 #include <stdlib.h>
     56 #include <string.h>
     57 #include <assert.h>
     58 
     59 /* User Include files */
     60 #include "ih264_typedefs.h"
     61 #include "iv2.h"
     62 #include "ive2.h"
     63 #include "ih264e.h"
     64 #include "ithread.h"
     65 #include "ih264_defs.h"
     66 #include "ih264_debug.h"
     67 #include "ime_distortion_metrics.h"
     68 #include "ime_defs.h"
     69 #include "ime_structs.h"
     70 #include "ih264_error.h"
     71 #include "ih264_structs.h"
     72 #include "ih264_trans_quant_itrans_iquant.h"
     73 #include "ih264_inter_pred_filters.h"
     74 #include "ih264_mem_fns.h"
     75 #include "ih264_padding.h"
     76 #include "ih264_intra_pred_filters.h"
     77 #include "ih264_deblk_edge_filters.h"
     78 #include "ih264_cabac_tables.h"
     79 #include "ih264_macros.h"
     80 #include "ih264_platform_macros.h"
     81 #include "ih264_buf_mgr.h"
     82 #include "ih264e_defs.h"
     83 #include "ih264e_error.h"
     84 #include "ih264e_bitstream.h"
     85 #include "irc_cntrl_param.h"
     86 #include "irc_frame_info_collector.h"
     87 #include "ih264e_rate_control.h"
     88 #include "ih264e_cabac_structs.h"
     89 #include "ih264e_structs.h"
     90 #include "ih264e_fmt_conv.h"
     91 
     92 
     93 /*****************************************************************************/
     94 /* Function Definitions                                                      */
     95 /*****************************************************************************/
     96 
     97 void ih264e_fmt_conv_420sp_to_rgb565(UWORD8 *pu1_y_src,
     98                                      UWORD8 *pu1_uv_src,
     99                                      UWORD16 *pu2_rgb_dst,
    100                                      WORD32 wd,
    101                                      WORD32 ht,
    102                                      WORD32 src_y_strd,
    103                                      WORD32 src_uv_strd,
    104                                      WORD32 dst_strd,
    105                                      WORD32 is_u_first)
    106 {
    107     WORD16 i2_r, i2_g, i2_b;
    108     UWORD32 u4_r, u4_g, u4_b;
    109     WORD16 i2_i, i2_j;
    110     UWORD8 *pu1_y_src_nxt;
    111     UWORD16 *pu2_rgb_dst_NextRow;
    112 
    113     UWORD8 *pu1_u_src, *pu1_v_src;
    114 
    115     if (is_u_first)
    116     {
    117         pu1_u_src = (UWORD8 *) pu1_uv_src;
    118         pu1_v_src = (UWORD8 *) pu1_uv_src + 1;
    119     }
    120     else
    121     {
    122         pu1_u_src = (UWORD8 *) pu1_uv_src + 1;
    123         pu1_v_src = (UWORD8 *) pu1_uv_src;
    124     }
    125 
    126     pu1_y_src_nxt = pu1_y_src + src_y_strd;
    127     pu2_rgb_dst_NextRow = pu2_rgb_dst + dst_strd;
    128 
    129     for (i2_i = 0; i2_i < (ht >> 1); i2_i++)
    130     {
    131         for (i2_j = (wd >> 1); i2_j > 0; i2_j--)
    132         {
    133             i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13);
    134             i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3)
    135                             >> 13;
    136             i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13;
    137 
    138             pu1_u_src += 2;
    139             pu1_v_src += 2;
    140             /* pixel 0 */
    141             /* B */
    142             u4_b = CLIP_U8(*pu1_y_src + i2_b);
    143             u4_b >>= 3;
    144             /* G */
    145             u4_g = CLIP_U8(*pu1_y_src + i2_g);
    146             u4_g >>= 2;
    147             /* R */
    148             u4_r = CLIP_U8(*pu1_y_src + i2_r);
    149             u4_r >>= 3;
    150 
    151             pu1_y_src++;
    152             *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
    153 
    154             /* pixel 1 */
    155             /* B */
    156             u4_b = CLIP_U8(*pu1_y_src + i2_b);
    157             u4_b >>= 3;
    158             /* G */
    159             u4_g = CLIP_U8(*pu1_y_src + i2_g);
    160             u4_g >>= 2;
    161             /* R */
    162             u4_r = CLIP_U8(*pu1_y_src + i2_r);
    163             u4_r >>= 3;
    164 
    165             pu1_y_src++;
    166             *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
    167 
    168             /* pixel 2 */
    169             /* B */
    170             u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
    171             u4_b >>= 3;
    172             /* G */
    173             u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
    174             u4_g >>= 2;
    175             /* R */
    176             u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
    177             u4_r >>= 3;
    178 
    179             pu1_y_src_nxt++;
    180             *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
    181 
    182             /* pixel 3 */
    183             /* B */
    184             u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
    185             u4_b >>= 3;
    186             /* G */
    187             u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
    188             u4_g >>= 2;
    189             /* R */
    190             u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
    191             u4_r >>= 3;
    192 
    193             pu1_y_src_nxt++;
    194             *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
    195 
    196         }
    197 
    198         pu1_u_src = pu1_u_src + src_uv_strd - wd;
    199         pu1_v_src = pu1_v_src + src_uv_strd - wd;
    200 
    201         pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd;
    202         pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd;
    203 
    204         pu2_rgb_dst = pu2_rgb_dst_NextRow - wd + dst_strd;
    205         pu2_rgb_dst_NextRow = pu2_rgb_dst_NextRow + (dst_strd << 1) - wd;
    206     }
    207 
    208 }
    209 
    210 void ih264e_fmt_conv_420sp_to_rgba8888(UWORD8 *pu1_y_src,
    211                                        UWORD8 *pu1_uv_src,
    212                                        UWORD32 *pu4_rgba_dst,
    213                                        WORD32 wd,
    214                                        WORD32 ht,
    215                                        WORD32 src_y_strd,
    216                                        WORD32 src_uv_strd,
    217                                        WORD32 dst_strd,
    218                                        WORD32 is_u_first)
    219 {
    220     WORD16 i2_r, i2_g, i2_b;
    221     UWORD32 u4_r, u4_g, u4_b;
    222     WORD16 i2_i, i2_j;
    223     UWORD8 *pu1_y_src_nxt;
    224     UWORD32 *pu4_rgba_dst_NextRow;
    225     UWORD8 *pu1_u_src, *pu1_v_src;
    226 
    227     if (is_u_first)
    228     {
    229         pu1_u_src = (UWORD8 *) pu1_uv_src;
    230         pu1_v_src = (UWORD8 *) pu1_uv_src + 1;
    231     }
    232     else
    233     {
    234         pu1_u_src = (UWORD8 *) pu1_uv_src + 1;
    235         pu1_v_src = (UWORD8 *) pu1_uv_src;
    236     }
    237 
    238     pu1_y_src_nxt = pu1_y_src + src_y_strd;
    239 
    240     pu4_rgba_dst_NextRow = pu4_rgba_dst + dst_strd;
    241 
    242     for (i2_i = 0; i2_i < (ht >> 1); i2_i++)
    243     {
    244         for (i2_j = (wd >> 1); i2_j > 0; i2_j--)
    245         {
    246             i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13);
    247             i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3)
    248                             >> 13;
    249             i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13;
    250 
    251             pu1_u_src += 2;
    252             pu1_v_src += 2;
    253             /* pixel 0 */
    254             /* B */
    255             u4_b = CLIP_U8(*pu1_y_src + i2_b);
    256             /* G */
    257             u4_g = CLIP_U8(*pu1_y_src + i2_g);
    258             /* R */
    259             u4_r = CLIP_U8(*pu1_y_src + i2_r);
    260 
    261             pu1_y_src++;
    262             *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
    263 
    264             /* pixel 1 */
    265             /* B */
    266             u4_b = CLIP_U8(*pu1_y_src + i2_b);
    267             /* G */
    268             u4_g = CLIP_U8(*pu1_y_src + i2_g);
    269             /* R */
    270             u4_r = CLIP_U8(*pu1_y_src + i2_r);
    271 
    272             pu1_y_src++;
    273             *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
    274 
    275             /* pixel 2 */
    276             /* B */
    277             u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
    278             /* G */
    279             u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
    280             /* R */
    281             u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
    282 
    283             pu1_y_src_nxt++;
    284             *pu4_rgba_dst_NextRow++ =
    285                             ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
    286 
    287             /* pixel 3 */
    288             /* B */
    289             u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
    290             /* G */
    291             u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
    292             /* R */
    293             u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
    294 
    295             pu1_y_src_nxt++;
    296             *pu4_rgba_dst_NextRow++ =
    297                             ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
    298 
    299         }
    300 
    301         pu1_u_src = pu1_u_src + src_uv_strd - wd;
    302         pu1_v_src = pu1_v_src + src_uv_strd - wd;
    303 
    304         pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd;
    305         pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd;
    306 
    307         pu4_rgba_dst = pu4_rgba_dst_NextRow - wd + dst_strd;
    308         pu4_rgba_dst_NextRow = pu4_rgba_dst_NextRow + (dst_strd << 1) - wd;
    309     }
    310 
    311 }
    312 
    313 /**
    314 *******************************************************************************
    315 *
    316 * @brief Function used for copying a 420SP buffer
    317 *
    318 * @par   Description
    319 *  Function used for copying a 420SP buffer
    320 *
    321 * @param[in] pu1_y_src
    322 *  Input Y pointer
    323 *
    324 * @param[in] pu1_uv_src
    325 *  Input UV pointer (UV is interleaved either in UV or VU format)
    326 *
    327 * @param[in] pu1_y_dst
    328 *  Output Y pointer
    329 *
    330 * @param[in] pu1_uv_dst
    331 *  Output UV pointer (UV is interleaved in the same format as that of input)
    332 *
    333 * @param[in] wd
    334 *  Width
    335 *
    336 * @param[in] ht
    337 *  Height
    338 *
    339 * @param[in] src_y_strd
    340 *  Input Y Stride
    341 *
    342 * @param[in] src_uv_strd
    343 *  Input UV stride
    344 *
    345 * @param[in] dst_y_strd
    346 *  Output Y stride
    347 *
    348 * @param[in] dst_uv_strd
    349 *  Output UV stride
    350 *
    351 * @returns None
    352 *
    353 * @remarks In case there is a need to perform partial frame copy then
    354 * by passion appropriate source and destination pointers and appropriate
    355 * values for wd and ht it can be done
    356 *
    357 *******************************************************************************
    358 */
    359 void ih264e_fmt_conv_420sp_to_420sp(UWORD8 *pu1_y_src,
    360                                     UWORD8 *pu1_uv_src,
    361                                     UWORD8 *pu1_y_dst,
    362                                     UWORD8 *pu1_uv_dst,
    363                                     WORD32 wd,
    364                                     WORD32 ht,
    365                                     WORD32 src_y_strd,
    366                                     WORD32 src_uv_strd,
    367                                     WORD32 dst_y_strd,
    368                                     WORD32 dst_uv_strd)
    369 {
    370     UWORD8 *pu1_src, *pu1_dst;
    371     WORD32 num_rows, num_cols, src_strd, dst_strd;
    372     WORD32 i;
    373 
    374     /* copy luma */
    375     pu1_src = (UWORD8 *) pu1_y_src;
    376     pu1_dst = (UWORD8 *) pu1_y_dst;
    377 
    378     num_rows = ht;
    379     num_cols = wd;
    380 
    381     src_strd = src_y_strd;
    382     dst_strd = dst_y_strd;
    383 
    384     for (i = 0; i < num_rows; i++)
    385     {
    386         memcpy(pu1_dst, pu1_src, num_cols);
    387         pu1_dst += dst_strd;
    388         pu1_src += src_strd;
    389     }
    390 
    391     /* copy U and V */
    392     pu1_src = (UWORD8 *) pu1_uv_src;
    393     pu1_dst = (UWORD8 *) pu1_uv_dst;
    394 
    395     num_rows = ht >> 1;
    396     num_cols = wd;
    397 
    398     src_strd = src_uv_strd;
    399     dst_strd = dst_uv_strd;
    400 
    401     for (i = 0; i < num_rows; i++)
    402     {
    403         memcpy(pu1_dst, pu1_src, num_cols);
    404         pu1_dst += dst_strd;
    405         pu1_src += src_strd;
    406     }
    407     return;
    408 }
    409 
    410 
    411 void ih264e_fmt_conv_420sp_to_420sp_swap_uv(UWORD8 *pu1_y_src,
    412                                             UWORD8 *pu1_uv_src,
    413                                             UWORD8 *pu1_y_dst,
    414                                             UWORD8 *pu1_uv_dst,
    415                                             WORD32 wd,
    416                                             WORD32 ht,
    417                                             WORD32 src_y_strd,
    418                                             WORD32 src_uv_strd,
    419                                             WORD32 dst_y_strd,
    420                                             WORD32 dst_uv_strd)
    421 {
    422     UWORD8 *pu1_src, *pu1_dst;
    423     WORD32 num_rows, num_cols, src_strd, dst_strd;
    424     WORD32 i;
    425 
    426     /* copy luma */
    427     pu1_src = (UWORD8 *) pu1_y_src;
    428     pu1_dst = (UWORD8 *) pu1_y_dst;
    429 
    430     num_rows = ht;
    431     num_cols = wd;
    432 
    433     src_strd = src_y_strd;
    434     dst_strd = dst_y_strd;
    435 
    436     for (i = 0; i < num_rows; i++)
    437     {
    438         memcpy(pu1_dst, pu1_src, num_cols);
    439         pu1_dst += dst_strd;
    440         pu1_src += src_strd;
    441     }
    442 
    443     /* copy U and V */
    444     pu1_src = (UWORD8 *) pu1_uv_src;
    445     pu1_dst = (UWORD8 *) pu1_uv_dst;
    446 
    447     num_rows = ht >> 1;
    448     num_cols = wd;
    449 
    450     src_strd = src_uv_strd;
    451     dst_strd = dst_uv_strd;
    452 
    453     for (i = 0; i < num_rows; i++)
    454     {
    455         WORD32 j;
    456         for (j = 0; j < num_cols; j += 2)
    457         {
    458             pu1_dst[j + 0] = pu1_src[j + 1];
    459             pu1_dst[j + 1] = pu1_src[j + 0];
    460         }
    461         pu1_dst += dst_strd;
    462         pu1_src += src_strd;
    463     }
    464     return;
    465 }
    466 
    467 void ih264e_fmt_conv_420sp_to_420p(UWORD8 *pu1_y_src,
    468                                    UWORD8 *pu1_uv_src,
    469                                    UWORD8 *pu1_y_dst,
    470                                    UWORD8 *pu1_u_dst,
    471                                    UWORD8 *pu1_v_dst,
    472                                    WORD32 wd,
    473                                    WORD32 ht,
    474                                    WORD32 src_y_strd,
    475                                    WORD32 src_uv_strd,
    476                                    WORD32 dst_y_strd,
    477                                    WORD32 dst_uv_strd,
    478                                    WORD32 is_u_first,
    479                                    WORD32 disable_luma_copy)
    480 {
    481     UWORD8 *pu1_src, *pu1_dst;
    482     UWORD8 *pu1_u_src, *pu1_v_src;
    483     WORD32 num_rows, num_cols, src_strd, dst_strd;
    484     WORD32 i, j;
    485 
    486     if (0 == disable_luma_copy)
    487     {
    488         /* copy luma */
    489         pu1_src = (UWORD8 *) pu1_y_src;
    490         pu1_dst = (UWORD8 *) pu1_y_dst;
    491 
    492         num_rows = ht;
    493         num_cols = wd;
    494 
    495         src_strd = src_y_strd;
    496         dst_strd = dst_y_strd;
    497 
    498         for (i = 0; i < num_rows; i++)
    499         {
    500             memcpy(pu1_dst, pu1_src, num_cols);
    501             pu1_dst += dst_strd;
    502             pu1_src += src_strd;
    503         }
    504     }
    505     /* de-interleave U and V and copy to destination */
    506     if (is_u_first)
    507     {
    508         pu1_u_src = (UWORD8 *) pu1_uv_src;
    509         pu1_v_src = (UWORD8 *) pu1_uv_src + 1;
    510     }
    511     else
    512     {
    513         pu1_u_src = (UWORD8 *) pu1_uv_src + 1;
    514         pu1_v_src = (UWORD8 *) pu1_uv_src;
    515     }
    516 
    517     num_rows = ht >> 1;
    518     num_cols = wd >> 1;
    519 
    520     src_strd = src_uv_strd;
    521     dst_strd = dst_uv_strd;
    522 
    523     for (i = 0; i < num_rows; i++)
    524     {
    525         for (j = 0; j < num_cols; j++)
    526         {
    527             pu1_u_dst[j] = pu1_u_src[j * 2];
    528             pu1_v_dst[j] = pu1_v_src[j * 2];
    529         }
    530 
    531         pu1_u_dst += dst_strd;
    532         pu1_v_dst += dst_strd;
    533         pu1_u_src += src_strd;
    534         pu1_v_src += src_strd;
    535     }
    536     return;
    537 }
    538 
    539 /**
    540 *******************************************************************************
    541 *
    542 * @brief Function used to perform color space conversion from 420P to 420SP
    543 *
    544 * @par   Description
    545 * Function used to perform color space conversion from 420P to 420SP
    546 *
    547 * @param[in] pu1_y_src
    548 *  Input Y pointer
    549 *
    550 * @param[in] pu1_u_src
    551 *  Input U pointer
    552 *
    553 * @param[in] pu1_v_dst
    554 *  Input V pointer
    555 *
    556 * @param[in] pu1_y_dst
    557 *  Output Y pointer
    558 *
    559 * @param[in] pu1_uv_dst
    560 *  Output UV pointer
    561 *
    562 * @param[in] u4_width
    563 *  Width
    564 *
    565 * @param[in] u4_height
    566 *  Height
    567 *
    568 * @param[in] src_y_strd
    569 *  Input Y Stride
    570 *
    571 * @param[in] src_u_strd
    572 *  Input U stride
    573 *
    574 * @param[in] src_v_strd
    575 *  Input V stride
    576 *
    577 * @param[in] dst_y_strd
    578 *  Output Y stride
    579 *
    580 * @param[in] dst_uv_strd
    581 *  Output UV stride
    582 *
    583 * @param[in] convert_uv_only
    584 *  Flag to indicate if only UV copy needs to be done
    585 *
    586 * @returns none
    587 *
    588 * @remarks In case there is a need to perform partial frame copy then
    589 * by passion appropriate source and destination pointers and appropriate
    590 * values for wd and ht it can be done
    591 *
    592 *******************************************************************************
    593 */
    594 void ih264e_fmt_conv_420p_to_420sp(UWORD8 *pu1_y_src,
    595                                    UWORD8 *pu1_u_src,
    596                                    UWORD8 *pu1_v_src,
    597                                    UWORD8 *pu1_y_dst,
    598                                    UWORD8 *pu1_uv_dst,
    599                                    UWORD16 u2_height,
    600                                    UWORD16 u2_width,
    601                                    UWORD16 src_y_strd,
    602                                    UWORD16 src_u_strd,
    603                                    UWORD16 src_v_strd,
    604                                    UWORD16 dst_y_strd,
    605                                    UWORD16 dst_uv_strd,
    606                                    UWORD32 convert_uv_only)
    607 {
    608     UWORD8 *pu1_src, *pu1_dst;
    609     UWORD8 *pu1_src_u, *pu1_src_v;
    610     UWORD16 i;
    611     UWORD32 u2_width_uv;
    612     UWORD32 dest_inc_Y = 0, dest_inc_UV = 0;
    613 
    614     dest_inc_UV = dst_uv_strd;
    615 
    616     if (0 == convert_uv_only)
    617     {
    618 
    619         /* Copy Y buffer */
    620         pu1_dst = (UWORD8 *) pu1_y_dst;
    621         pu1_src = (UWORD8 *) pu1_y_src;
    622 
    623         dest_inc_Y = dst_y_strd;
    624 
    625         for (i = 0; i < u2_height; i++)
    626         {
    627             memcpy((void *) pu1_dst, (void *) pu1_src, u2_width);
    628             pu1_dst += dest_inc_Y;
    629             pu1_src += src_y_strd;
    630         }
    631     }
    632 
    633     /* Interleave Cb and Cr buffers */
    634     pu1_src_u = pu1_u_src;
    635     pu1_src_v = pu1_v_src;
    636     pu1_dst = pu1_uv_dst;
    637 
    638     u2_height = (u2_height + 1) >> 1;
    639     u2_width_uv = (u2_width + 1) >> 1;
    640     for (i = 0; i < u2_height; i++)
    641     {
    642         UWORD32 j;
    643         for (j = 0; j < u2_width_uv; j++)
    644         {
    645             *pu1_dst++ = *pu1_src_u++;
    646             *pu1_dst++ = *pu1_src_v++;
    647         }
    648 
    649         pu1_dst += dest_inc_UV - u2_width;
    650         pu1_src_u += src_u_strd - u2_width_uv;
    651         pu1_src_v += src_v_strd - u2_width_uv;
    652     }
    653 }
    654 
    655 /**
    656 *******************************************************************************
    657 *
    658 * @brief Function used to convert 422 interleaved to 420sp
    659 *
    660 * @par   Description
    661 *  Function used to convert 422 interleaved to 420sp
    662 *
    663 * @param[in] pu1_y_buf
    664 *  Output Y pointer
    665 *
    666 * @param[in] pu1_u_buf
    667 *  Output u pointer
    668 *
    669 * @param[in[ pu1_v_buf
    670 *  Output V pointer
    671 *
    672 * @param[in] pu1_422i_buf
    673 *  Input 422i pointer
    674 *
    675 * @param[in] u4_y_width
    676 *  Width of Y component
    677 *
    678 * @param[in] u4_y_height
    679 *  Height of Y component
    680 *
    681 * @param[in] u4_y_stride
    682 *  Stride of pu1_y_buf
    683 *
    684 * @param[in] u4_u_stride
    685 *  Stride of pu1_u_buf
    686 *
    687 * @param[in] u4_v_stride
    688 *  Stride of pu1_v_buf
    689 *
    690 * @param[in] u4_422i_stride
    691 *  Stride of pu1_422i_buf
    692 *
    693 * @returns None
    694 *
    695 * @remarks For conversion
    696 * pu1_v_buf = pu1_u_buf+1
    697 * u4_u_stride = u4_v_stride
    698 *
    699 * The extra parameters are for maintaining API with assembly function
    700 *
    701 *******************************************************************************
    702 */
    703 void ih264e_fmt_conv_422i_to_420sp(UWORD8 *pu1_y_buf,
    704                                    UWORD8 *pu1_u_buf,
    705                                    UWORD8 *pu1_v_buf,
    706                                    UWORD8 *pu1_422i_buf,
    707                                    WORD32 u4_y_width,
    708                                    WORD32 u4_y_height,
    709                                    WORD32 u4_y_stride,
    710                                    WORD32 u4_u_stride,
    711                                    WORD32 u4_v_stride,
    712                                    WORD32 u4_422i_stride)
    713 {
    714     WORD32 row, col;
    715     UWORD8 *row_even_422 = pu1_422i_buf;
    716     UWORD8 *row_odd_422 = row_even_422 + (u4_422i_stride << 1);
    717     UWORD8 *row_even_luma = pu1_y_buf;
    718     /* Since at the end of loop, we have row_even_luma += (luma_width << 1),
    719      * it should be same here right? */
    720     UWORD8 *row_odd_luma = row_even_luma + u4_y_stride;
    721     UWORD8 *row_cb = pu1_u_buf;
    722     UWORD8 *row_cr = pu1_v_buf;
    723 
    724     for (row = 0; row < u4_y_height; row = row + 2)
    725     {
    726         for (col = 0; col < (u4_y_width << 1); col = col + 4)
    727         {
    728             UWORD8 cb_even = row_even_422[col];
    729             UWORD8 cr_even = row_even_422[col + 2];
    730 
    731             row_cb[col >> 1] = cb_even;
    732             row_cr[col >> 1] = cr_even;
    733 
    734             row_even_luma[col >> 1] = row_even_422[col + 1];
    735             row_even_luma[(col >> 1) + 1] = row_even_422[col + 3];
    736 
    737             row_odd_luma[col >> 1] = row_odd_422[col + 1];
    738             row_odd_luma[(col >> 1) + 1] = row_odd_422[col + 3];
    739         }
    740 
    741         row_even_422 += (u4_422i_stride << 2);
    742         row_odd_422 += (u4_422i_stride << 2);
    743 
    744         row_even_luma += (u4_y_stride << 1);
    745         row_odd_luma += (u4_y_stride << 1);
    746 
    747         row_cb += u4_u_stride;
    748         row_cr += u4_v_stride;
    749     }
    750 }
    751 
    752 /**
    753 *******************************************************************************
    754 *
    755 * @brief Function used from format conversion or frame copy
    756 *
    757 * @par   Description
    758 * Function used from copying or converting a reference frame to display buffer
    759 * in non shared mode
    760 *
    761 * @param[in] pu1_y_dst
    762 *  Output Y pointer
    763 *
    764 * @param[in] pu1_u_dst
    765 *  Output U/UV pointer ( UV is interleaved in the same format as that of input)
    766 *
    767 * @param[in] pu1_v_dst
    768 *  Output V pointer ( used in 420P output case)
    769 *
    770 * @param[in] u4_dst_y_strd
    771 *  Stride of destination Y buffer
    772 *
    773 * @param[in] u4_dst_u_strd
    774 *  Stride of destination  U/V buffer
    775 *
    776 * @param[in] blocking
    777 *  To indicate whether format conversion should wait till frame is reconstructed
    778 *  and then return after complete copy is done. To be set to 1 when called at the
    779 *  end of frame processing and set to 0 when called between frame processing modules
    780 *  in order to utilize available MCPS
    781 *
    782 * @returns error status
    783 *
    784 * @remarks
    785 * Assumes that the stride of U and V buffers are same.
    786 * This is correct in most cases
    787 * If a case comes where this is not true we need to modify the fmt conversion
    788 * functions called inside also
    789 *
    790 *******************************************************************************
    791 */
    792 IH264E_ERROR_T ih264e_fmt_conv(codec_t *ps_codec,
    793                                pic_buf_t *ps_pic,
    794                                UWORD8 *pu1_y_dst,
    795                                UWORD8 *pu1_u_dst,
    796                                UWORD8 *pu1_v_dst,
    797                                UWORD32 u4_dst_y_strd,
    798                                UWORD32 u4_dst_uv_strd,
    799                                WORD32 cur_row,
    800                                WORD32 num_rows)
    801 {
    802     IH264E_ERROR_T ret = IH264E_SUCCESS;
    803     UWORD8 *pu1_y_src, *pu1_uv_src;
    804     UWORD8 *pu1_y_dst_tmp, *pu1_uv_dst_tmp;
    805     UWORD8 *pu1_u_dst_tmp, *pu1_v_dst_tmp;
    806     UWORD16 *pu2_rgb_dst_tmp;
    807     UWORD32 *pu4_rgb_dst_tmp;
    808     WORD32 is_u_first;
    809     UWORD8 *pu1_luma;
    810     UWORD8 *pu1_chroma;
    811     WORD32 dst_stride, wd;
    812 
    813 
    814     if (0 == num_rows)
    815         return ret;
    816 
    817     pu1_luma = ps_pic->pu1_luma;
    818     pu1_chroma = ps_pic->pu1_chroma;
    819 
    820 
    821     dst_stride = ps_codec->s_cfg.u4_wd;
    822     wd = ps_codec->s_cfg.u4_disp_wd;
    823     is_u_first = (IV_YUV_420SP_UV == ps_codec->e_codec_color_format) ? 1 : 0;
    824 
    825     /* In case of 420P output luma copy is disabled for shared mode */
    826     {
    827         pu1_y_src = pu1_luma + cur_row * ps_codec->i4_rec_strd;
    828         pu1_uv_src = pu1_chroma + (cur_row / 2) * ps_codec->i4_rec_strd;
    829 
    830         pu2_rgb_dst_tmp = (UWORD16 *) pu1_y_dst;
    831         pu2_rgb_dst_tmp += cur_row * dst_stride;
    832         pu4_rgb_dst_tmp = (UWORD32 *) pu1_y_dst;
    833         pu4_rgb_dst_tmp += cur_row * dst_stride;
    834 
    835         pu1_y_dst_tmp = pu1_y_dst + cur_row * u4_dst_y_strd;
    836         pu1_uv_dst_tmp = pu1_u_dst + (cur_row / 2) * u4_dst_uv_strd;
    837         pu1_u_dst_tmp = pu1_u_dst + (cur_row / 2) * u4_dst_uv_strd;
    838         pu1_v_dst_tmp = pu1_v_dst + (cur_row / 2) * u4_dst_uv_strd;
    839 
    840         /* If the call is non-blocking and there are no rows to be copied then return */
    841         /* In non-shared mode, reference buffers are in 420SP UV format,
    842          * if output also is in 420SP_UV, then just copy
    843          * if output is in 420SP_VU then swap UV values
    844          */
    845         if ((IV_YUV_420SP_UV == ps_codec->s_cfg.e_recon_color_fmt) ||
    846                         (IV_YUV_420SP_VU == ps_codec->s_cfg.e_recon_color_fmt))
    847         {
    848             ih264e_fmt_conv_420sp_to_420sp(pu1_y_src, pu1_uv_src, pu1_y_dst_tmp,
    849                                            pu1_uv_dst_tmp, wd, num_rows,
    850                                            ps_codec->i4_rec_strd,
    851                                            ps_codec->i4_rec_strd, u4_dst_y_strd,
    852                                            u4_dst_uv_strd);
    853         }
    854         else if (IV_YUV_420P == ps_codec->s_cfg.e_recon_color_fmt)
    855         {
    856             ih264e_fmt_conv_420sp_to_420p(pu1_y_src, pu1_uv_src, pu1_y_dst_tmp,
    857                                           pu1_u_dst_tmp, pu1_v_dst_tmp, wd,
    858                                           num_rows, ps_codec->i4_rec_strd,
    859                                           ps_codec->i4_rec_strd, u4_dst_y_strd,
    860                                           u4_dst_uv_strd, is_u_first, 0);
    861         }
    862     }
    863     return(ret);
    864 }
    865 
    866