/****************************************************************************** * * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ******************************************************************************/ /** ******************************************************************************* * @file * ihevcd_fmt_conv.c * * @brief * Contains functions for format conversion or frame copy of output buffer * * @author * Harish * * @par List of Functions: * * @remarks * None * ******************************************************************************* */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ #include <stdio.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <assert.h> #include "ihevc_typedefs.h" #include "iv.h" #include "ivd.h" #include "ihevcd_cxa.h" #include "ithread.h" #include "ihevc_defs.h" #include "ihevc_debug.h" #include "ihevc_structs.h" #include "ihevc_macros.h" #include "ihevc_platform_macros.h" #include "ihevc_cabac_tables.h" #include "ihevc_disp_mgr.h" #include "ihevcd_defs.h" #include "ihevcd_function_selector.h" #include "ihevcd_structs.h" #include "ihevcd_error.h" #include "ihevcd_nal.h" #include "ihevcd_bitstream.h" #include "ihevcd_fmt_conv.h" #include "ihevcd_profile.h" /** ******************************************************************************* * * @brief Function used from copying a 420SP buffer * * @par Description * Function used from copying a 420SP buffer * * @param[in] pu1_y_src * Input Y pointer * * @param[in] pu1_uv_src * Input UV pointer (UV is interleaved either in UV or VU format) * * @param[in] pu1_y_dst * Output Y pointer * * @param[in] pu1_uv_dst * Output UV pointer (UV is interleaved in the same format as that of input) * * @param[in] wd * Width * * @param[in] ht * Height * * @param[in] src_y_strd * Input Y Stride * * @param[in] src_uv_strd * Input UV stride * * @param[in] dst_y_strd * Output Y stride * * @param[in] dst_uv_strd * Output UV stride * * @returns None * * @remarks In case there is a need to perform partial frame copy then * by passion appropriate source and destination pointers and appropriate * values for wd and ht it can be done * ******************************************************************************* */ void ihevcd_fmt_conv_420sp_to_rgb565(UWORD8 *pu1_y_src, UWORD8 *pu1_uv_src, UWORD16 *pu2_rgb_dst, WORD32 wd, WORD32 ht, WORD32 src_y_strd, WORD32 src_uv_strd, WORD32 dst_strd, WORD32 is_u_first) { WORD16 i2_r, i2_g, i2_b; UWORD32 u4_r, u4_g, u4_b; WORD16 i2_i, i2_j; UWORD8 *pu1_y_src_nxt; UWORD16 *pu2_rgb_dst_NextRow; UWORD8 *pu1_u_src, *pu1_v_src; if(is_u_first) { pu1_u_src = (UWORD8 *)pu1_uv_src; pu1_v_src = (UWORD8 *)pu1_uv_src + 1; } else { pu1_u_src = (UWORD8 *)pu1_uv_src + 1; pu1_v_src = (UWORD8 *)pu1_uv_src; } pu1_y_src_nxt = pu1_y_src + src_y_strd; pu2_rgb_dst_NextRow = pu2_rgb_dst + dst_strd; for(i2_i = 0; i2_i < (ht >> 1); i2_i++) { for(i2_j = (wd >> 1); i2_j > 0; i2_j--) { i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13); i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3) >> 13; i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13; pu1_u_src += 2; pu1_v_src += 2; /* pixel 0 */ /* B */ u4_b = CLIP_U8(*pu1_y_src + i2_b); u4_b >>= 3; /* G */ u4_g = CLIP_U8(*pu1_y_src + i2_g); u4_g >>= 2; /* R */ u4_r = CLIP_U8(*pu1_y_src + i2_r); u4_r >>= 3; pu1_y_src++; *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b); /* pixel 1 */ /* B */ u4_b = CLIP_U8(*pu1_y_src + i2_b); u4_b >>= 3; /* G */ u4_g = CLIP_U8(*pu1_y_src + i2_g); u4_g >>= 2; /* R */ u4_r = CLIP_U8(*pu1_y_src + i2_r); u4_r >>= 3; pu1_y_src++; *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b); /* pixel 2 */ /* B */ u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); u4_b >>= 3; /* G */ u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); u4_g >>= 2; /* R */ u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); u4_r >>= 3; pu1_y_src_nxt++; *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b); /* pixel 3 */ /* B */ u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); u4_b >>= 3; /* G */ u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); u4_g >>= 2; /* R */ u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); u4_r >>= 3; pu1_y_src_nxt++; *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b); } pu1_u_src = pu1_u_src + src_uv_strd - wd; pu1_v_src = pu1_v_src + src_uv_strd - wd; pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd; pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd; pu2_rgb_dst = pu2_rgb_dst_NextRow - wd + dst_strd; pu2_rgb_dst_NextRow = pu2_rgb_dst_NextRow + (dst_strd << 1) - wd; } } void ihevcd_fmt_conv_420sp_to_rgba8888(UWORD8 *pu1_y_src, UWORD8 *pu1_uv_src, UWORD32 *pu4_rgba_dst, WORD32 wd, WORD32 ht, WORD32 src_y_strd, WORD32 src_uv_strd, WORD32 dst_strd, WORD32 is_u_first) { WORD16 i2_r, i2_g, i2_b; UWORD32 u4_r, u4_g, u4_b; WORD16 i2_i, i2_j; UWORD8 *pu1_y_src_nxt; UWORD32 *pu4_rgba_dst_NextRow; UWORD8 *pu1_u_src, *pu1_v_src; if(is_u_first) { pu1_u_src = (UWORD8 *)pu1_uv_src; pu1_v_src = (UWORD8 *)pu1_uv_src + 1; } else { pu1_u_src = (UWORD8 *)pu1_uv_src + 1; pu1_v_src = (UWORD8 *)pu1_uv_src; } pu1_y_src_nxt = pu1_y_src + src_y_strd; pu4_rgba_dst_NextRow = pu4_rgba_dst + dst_strd; for(i2_i = 0; i2_i < (ht >> 1); i2_i++) { for(i2_j = (wd >> 1); i2_j > 0; i2_j--) { i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13); i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3) >> 13; i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13; pu1_u_src += 2; pu1_v_src += 2; /* pixel 0 */ /* B */ u4_b = CLIP_U8(*pu1_y_src + i2_b); /* G */ u4_g = CLIP_U8(*pu1_y_src + i2_g); /* R */ u4_r = CLIP_U8(*pu1_y_src + i2_r); pu1_y_src++; *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); /* pixel 1 */ /* B */ u4_b = CLIP_U8(*pu1_y_src + i2_b); /* G */ u4_g = CLIP_U8(*pu1_y_src + i2_g); /* R */ u4_r = CLIP_U8(*pu1_y_src + i2_r); pu1_y_src++; *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); /* pixel 2 */ /* B */ u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); /* G */ u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); /* R */ u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); pu1_y_src_nxt++; *pu4_rgba_dst_NextRow++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); /* pixel 3 */ /* B */ u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b); /* G */ u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g); /* R */ u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r); pu1_y_src_nxt++; *pu4_rgba_dst_NextRow++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0)); } pu1_u_src = pu1_u_src + src_uv_strd - wd; pu1_v_src = pu1_v_src + src_uv_strd - wd; pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd; pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd; pu4_rgba_dst = pu4_rgba_dst_NextRow - wd + dst_strd; pu4_rgba_dst_NextRow = pu4_rgba_dst_NextRow + (dst_strd << 1) - wd; } } /** ******************************************************************************* * * @brief Function used from copying a 420SP buffer * * @par Description * Function used from copying a 420SP buffer * * @param[in] pu1_y_src * Input Y pointer * * @param[in] pu1_uv_src * Input UV pointer (UV is interleaved either in UV or VU format) * * @param[in] pu1_y_dst * Output Y pointer * * @param[in] pu1_uv_dst * Output UV pointer (UV is interleaved in the same format as that of input) * * @param[in] wd * Width * * @param[in] ht * Height * * @param[in] src_y_strd * Input Y Stride * * @param[in] src_uv_strd * Input UV stride * * @param[in] dst_y_strd * Output Y stride * * @param[in] dst_uv_strd * Output UV stride * * @returns None * * @remarks In case there is a need to perform partial frame copy then * by passion appropriate source and destination pointers and appropriate * values for wd and ht it can be done * ******************************************************************************* */ void ihevcd_fmt_conv_420sp_to_420sp(UWORD8 *pu1_y_src, UWORD8 *pu1_uv_src, UWORD8 *pu1_y_dst, UWORD8 *pu1_uv_dst, WORD32 wd, WORD32 ht, WORD32 src_y_strd, WORD32 src_uv_strd, WORD32 dst_y_strd, WORD32 dst_uv_strd) { UWORD8 *pu1_src, *pu1_dst; WORD32 num_rows, num_cols, src_strd, dst_strd; WORD32 i; /* copy luma */ pu1_src = (UWORD8 *)pu1_y_src; pu1_dst = (UWORD8 *)pu1_y_dst; num_rows = ht; num_cols = wd; src_strd = src_y_strd; dst_strd = dst_y_strd; for(i = 0; i < num_rows; i++) { memcpy(pu1_dst, pu1_src, num_cols); pu1_dst += dst_strd; pu1_src += src_strd; } /* copy U and V */ pu1_src = (UWORD8 *)pu1_uv_src; pu1_dst = (UWORD8 *)pu1_uv_dst; num_rows = ht >> 1; num_cols = wd; src_strd = src_uv_strd; dst_strd = dst_uv_strd; for(i = 0; i < num_rows; i++) { memcpy(pu1_dst, pu1_src, num_cols); pu1_dst += dst_strd; pu1_src += src_strd; } return; } /** ******************************************************************************* * * @brief Function used from copying a 420SP buffer * * @par Description * Function used from copying a 420SP buffer * * @param[in] pu1_y_src * Input Y pointer * * @param[in] pu1_uv_src * Input UV pointer (UV is interleaved either in UV or VU format) * * @param[in] pu1_y_dst * Output Y pointer * * @param[in] pu1_uv_dst * Output UV pointer (UV is interleaved in the same format as that of input) * * @param[in] wd * Width * * @param[in] ht * Height * * @param[in] src_y_strd * Input Y Stride * * @param[in] src_uv_strd * Input UV stride * * @param[in] dst_y_strd * Output Y stride * * @param[in] dst_uv_strd * Output UV stride * * @returns None * * @remarks In case there is a need to perform partial frame copy then * by passion appropriate source and destination pointers and appropriate * values for wd and ht it can be done * ******************************************************************************* */ void ihevcd_fmt_conv_420sp_to_420sp_swap_uv(UWORD8 *pu1_y_src, UWORD8 *pu1_uv_src, UWORD8 *pu1_y_dst, UWORD8 *pu1_uv_dst, WORD32 wd, WORD32 ht, WORD32 src_y_strd, WORD32 src_uv_strd, WORD32 dst_y_strd, WORD32 dst_uv_strd) { UWORD8 *pu1_src, *pu1_dst; WORD32 num_rows, num_cols, src_strd, dst_strd; WORD32 i; /* copy luma */ pu1_src = (UWORD8 *)pu1_y_src; pu1_dst = (UWORD8 *)pu1_y_dst; num_rows = ht; num_cols = wd; src_strd = src_y_strd; dst_strd = dst_y_strd; for(i = 0; i < num_rows; i++) { memcpy(pu1_dst, pu1_src, num_cols); pu1_dst += dst_strd; pu1_src += src_strd; } /* copy U and V */ pu1_src = (UWORD8 *)pu1_uv_src; pu1_dst = (UWORD8 *)pu1_uv_dst; num_rows = ht >> 1; num_cols = wd; src_strd = src_uv_strd; dst_strd = dst_uv_strd; for(i = 0; i < num_rows; i++) { WORD32 j; for(j = 0; j < num_cols; j += 2) { pu1_dst[j + 0] = pu1_src[j + 1]; pu1_dst[j + 1] = pu1_src[j + 0]; } pu1_dst += dst_strd; pu1_src += src_strd; } return; } /** ******************************************************************************* * * @brief Function used from copying a 420SP buffer * * @par Description * Function used from copying a 420SP buffer * * @param[in] pu1_y_src * Input Y pointer * * @param[in] pu1_uv_src * Input UV pointer (UV is interleaved either in UV or VU format) * * @param[in] pu1_y_dst * Output Y pointer * * @param[in] pu1_u_dst * Output U pointer * * @param[in] pu1_v_dst * Output V pointer * * @param[in] wd * Width * * @param[in] ht * Height * * @param[in] src_y_strd * Input Y Stride * * @param[in] src_uv_strd * Input UV stride * * @param[in] dst_y_strd * Output Y stride * * @param[in] dst_uv_strd * Output UV stride * * @param[in] is_u_first * Flag to indicate if U is the first byte in input chroma part * * @returns none * * @remarks In case there is a need to perform partial frame copy then * by passion appropriate source and destination pointers and appropriate * values for wd and ht it can be done * ******************************************************************************* */ void ihevcd_fmt_conv_420sp_to_420p(UWORD8 *pu1_y_src, UWORD8 *pu1_uv_src, UWORD8 *pu1_y_dst, UWORD8 *pu1_u_dst, UWORD8 *pu1_v_dst, WORD32 wd, WORD32 ht, WORD32 src_y_strd, WORD32 src_uv_strd, WORD32 dst_y_strd, WORD32 dst_uv_strd, WORD32 is_u_first, WORD32 disable_luma_copy) { UWORD8 *pu1_src, *pu1_dst; UWORD8 *pu1_u_src, *pu1_v_src; WORD32 num_rows, num_cols, src_strd, dst_strd; WORD32 i, j; if(0 == disable_luma_copy) { /* copy luma */ pu1_src = (UWORD8 *)pu1_y_src; pu1_dst = (UWORD8 *)pu1_y_dst; num_rows = ht; num_cols = wd; src_strd = src_y_strd; dst_strd = dst_y_strd; for(i = 0; i < num_rows; i++) { memcpy(pu1_dst, pu1_src, num_cols); pu1_dst += dst_strd; pu1_src += src_strd; } } /* de-interleave U and V and copy to destination */ if(is_u_first) { pu1_u_src = (UWORD8 *)pu1_uv_src; pu1_v_src = (UWORD8 *)pu1_uv_src + 1; } else { pu1_u_src = (UWORD8 *)pu1_uv_src + 1; pu1_v_src = (UWORD8 *)pu1_uv_src; } num_rows = ht >> 1; num_cols = wd >> 1; src_strd = src_uv_strd; dst_strd = dst_uv_strd; for(i = 0; i < num_rows; i++) { for(j = 0; j < num_cols; j++) { pu1_u_dst[j] = pu1_u_src[j * 2]; pu1_v_dst[j] = pu1_v_src[j * 2]; } pu1_u_dst += dst_strd; pu1_v_dst += dst_strd; pu1_u_src += src_strd; pu1_v_src += src_strd; } return; } /** ******************************************************************************* * * @brief Function used from format conversion or frame copy * * @par Description * Function used from copying or converting a reference frame to display buffer * in non shared mode * * @param[in] pu1_y_dst * Output Y pointer * * @param[in] pu1_u_dst * Output U/UV pointer ( UV is interleaved in the same format as that of input) * * @param[in] pu1_v_dst * Output V pointer ( used in 420P output case) * * @param[in] blocking * To indicate whether format conversion should wait till frame is reconstructed * and then return after complete copy is done. To be set to 1 when called at the * end of frame processing and set to 0 when called between frame processing modules * in order to utilize available MCPS * * @returns Error from IHEVCD_ERROR_T * ******************************************************************************* */ IHEVCD_ERROR_T ihevcd_fmt_conv(codec_t *ps_codec, process_ctxt_t *ps_proc, UWORD8 *pu1_y_dst, UWORD8 *pu1_u_dst, UWORD8 *pu1_v_dst, WORD32 cur_row, WORD32 num_rows) { IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS; pic_buf_t *ps_disp_pic; UWORD8 *pu1_y_src, *pu1_uv_src; UWORD8 *pu1_y_dst_tmp, *pu1_uv_dst_tmp; UWORD8 *pu1_u_dst_tmp, *pu1_v_dst_tmp; UWORD16 *pu2_rgb_dst_tmp; UWORD32 *pu4_rgb_dst_tmp; WORD32 is_u_first; UWORD8 *pu1_luma; UWORD8 *pu1_chroma; sps_t *ps_sps; WORD32 disable_luma_copy; WORD32 crop_unit_x, crop_unit_y; if(0 == num_rows) return ret; /* In case processing is disabled, then no need to format convert/copy */ PROFILE_DISABLE_FMT_CONV(); ps_sps = ps_proc->ps_sps; crop_unit_x = 1; crop_unit_y = 1; if(CHROMA_FMT_IDC_YUV420 == ps_sps->i1_chroma_format_idc) { crop_unit_x = 2; crop_unit_y = 2; } ps_disp_pic = ps_codec->ps_disp_buf; pu1_luma = ps_disp_pic->pu1_luma; pu1_chroma = ps_disp_pic->pu1_chroma; /* Take care of cropping */ 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; /* Left offset is multiplied by 2 because buffer is UV interleaved */ pu1_chroma += ps_codec->i4_strd * ps_sps->i2_pic_crop_top_offset + ps_sps->i2_pic_crop_left_offset * 2; is_u_first = (IV_YUV_420SP_UV == ps_codec->e_ref_chroma_fmt) ? 1 : 0; /* In case of 420P output luma copy is disabled for shared mode */ disable_luma_copy = 0; if(1 == ps_codec->i4_share_disp_buf) { disable_luma_copy = 1; } { pu1_y_src = pu1_luma + cur_row * ps_codec->i4_strd; pu1_uv_src = pu1_chroma + (cur_row / 2) * ps_codec->i4_strd; pu2_rgb_dst_tmp = (UWORD16 *)pu1_y_dst; pu2_rgb_dst_tmp += cur_row * ps_codec->i4_disp_strd; pu4_rgb_dst_tmp = (UWORD32 *)pu1_y_dst; pu4_rgb_dst_tmp += cur_row * ps_codec->i4_disp_strd; pu1_y_dst_tmp = pu1_y_dst + cur_row * ps_codec->i4_disp_strd; pu1_uv_dst_tmp = pu1_u_dst + (cur_row / 2) * ps_codec->i4_disp_strd; pu1_u_dst_tmp = pu1_u_dst + (cur_row / 2) * ps_codec->i4_disp_strd / 2; pu1_v_dst_tmp = pu1_v_dst + (cur_row / 2) * ps_codec->i4_disp_strd / 2; /* In case of multi threaded implementation, format conversion might be called * before reconstruction is completed. If the frame being converted/copied * is same as the frame being reconstructed, * Check how many rows can be format converted * Convert those many rows and then check for remaining rows and so on */ 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)) { WORD32 idx; UWORD8 *pu1_buf; WORD32 status; WORD32 last_row = cur_row + num_rows; WORD32 last_ctb_y; UWORD32 ctb_in_row; while(1) { last_row = cur_row + MAX(num_rows, (1 << ps_sps->i1_log2_ctb_size)) + ps_sps->i2_pic_crop_top_offset * crop_unit_y; last_ctb_y = (last_row >> ps_sps->i1_log2_ctb_size) - 1; /* Since deblocking works with a shift of -4, -4 ,wait till next CTB row is processed */ last_ctb_y++; /* In case of a conformance window, an extra wait of one row might be needed */ last_ctb_y++; last_ctb_y = MIN(last_ctb_y, (ps_sps->i2_pic_ht_in_ctb - 1)); idx = (last_ctb_y * ps_sps->i2_pic_wd_in_ctb); /*Check if the row below is completely processed before proceeding with format conversion*/ status = 1; for(ctb_in_row = 0; (WORD32)ctb_in_row < ps_sps->i2_pic_wd_in_ctb; ctb_in_row++) { pu1_buf = (ps_codec->pu1_proc_map + idx + ctb_in_row); status &= *pu1_buf; } if(status) { break; } else { ithread_yield(); } } } if((IV_YUV_420SP_UV == ps_codec->e_chroma_fmt) || (IV_YUV_420SP_VU == ps_codec->e_chroma_fmt)) { ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420sp_fptr(pu1_y_src, pu1_uv_src, pu1_y_dst_tmp, pu1_uv_dst_tmp, ps_codec->i4_disp_wd, num_rows, ps_codec->i4_strd, ps_codec->i4_strd, ps_codec->i4_disp_strd, ps_codec->i4_disp_strd); } else if(IV_YUV_420P == ps_codec->e_chroma_fmt) { if(0 == disable_luma_copy) { // copy luma WORD32 i; WORD32 num_cols = ps_codec->i4_disp_wd; for(i = 0; i < num_rows; i++) { memcpy(pu1_y_dst_tmp, pu1_y_src, num_cols); pu1_y_dst_tmp += ps_codec->i4_disp_strd; pu1_y_src += ps_codec->i4_strd; } disable_luma_copy = 1; } ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420p_fptr(pu1_y_src, pu1_uv_src, pu1_y_dst_tmp, pu1_u_dst_tmp, pu1_v_dst_tmp, ps_codec->i4_disp_wd, num_rows, ps_codec->i4_strd, ps_codec->i4_strd, ps_codec->i4_disp_strd, (ps_codec->i4_disp_strd / 2), is_u_first, disable_luma_copy); } else if(IV_RGB_565 == ps_codec->e_chroma_fmt) { ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgb565_fptr(pu1_y_src, pu1_uv_src, pu2_rgb_dst_tmp, ps_codec->i4_disp_wd, num_rows, ps_codec->i4_strd, ps_codec->i4_strd, ps_codec->i4_disp_strd, is_u_first); } else if(IV_RGBA_8888 == ps_codec->e_chroma_fmt) { ASSERT(is_u_first == 1); ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgba8888_fptr(pu1_y_src, pu1_uv_src, pu4_rgb_dst_tmp, ps_codec->i4_disp_wd, num_rows, ps_codec->i4_strd, ps_codec->i4_strd, ps_codec->i4_disp_strd, is_u_first); } } return (ret); }