diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.c b/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.c index df5e4364..d00a9e6c 100644 --- a/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.c +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu1_v2.c @@ -371,7 +371,7 @@ static MPP_RET hal_h264e_vepu1_gen_regs_v2(void *hal, HalEncTask *task) // When offset is zero row length should be total 16 aligned width val = VEPU_REG_IN_IMG_CHROMA_OFFSET(0) | VEPU_REG_IN_IMG_LUMA_OFFSET(0) - | VEPU_REG_IN_IMG_CTRL_ROW_LEN(hw_prep->hor_stride) + | VEPU_REG_IN_IMG_CTRL_ROW_LEN(hw_prep->pixel_stride) | VEPU_REG_IN_IMG_CTRL_OVRFLR_D4(overfill_r) | VEPU_REG_IN_IMG_CTRL_OVRFLB(overfill_b) | VEPU_REG_IN_IMG_CTRL_FMT(hw_prep->src_fmt) diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.c b/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.c index 440d0277..51712c48 100644 --- a/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.c +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu2_v2.c @@ -363,7 +363,7 @@ static MPP_RET hal_h264e_vepu2_gen_regs_v2(void *hal, HalEncTask *task) // When offset is zero row length should be total 16 aligned width val = VEPU_REG_IN_IMG_CHROMA_OFFSET(0) | VEPU_REG_IN_IMG_LUMA_OFFSET(0) - | VEPU_REG_IN_IMG_CTRL_ROW_LEN(hw_prep->hor_stride); + | VEPU_REG_IN_IMG_CTRL_ROW_LEN(hw_prep->pixel_stride); H264E_HAL_SET_REG(reg, VEPU_REG_INPUT_LUMA_INFO, val); diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.c b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.c index c0c3be4f..bb5daa1e 100644 --- a/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.c +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.c @@ -299,6 +299,35 @@ MppBuffer h264e_vepu_buf_get_frame_buffer(HalH264eVepuBufs *bufs, RK_S32 index) return buf; } +static RK_S32 check_stride_by_pixel(RK_S32 workaround, RK_S32 width, + RK_S32 hor_stride, RK_S32 pixel_size) +{ + if (!workaround && hor_stride < width * pixel_size) { + mpp_log("warning: stride by bytes %d is smarller than width %d mutiple by pixel size %d\n", + hor_stride, width, pixel_size); + mpp_log("multiple stride %d by pixel size %d and set new byte stride to %d\n", + hor_stride, pixel_size, hor_stride * pixel_size); + workaround = 1; + } + + return workaround; +} + +static RK_S32 check_8_pixel_aligned(RK_S32 workaround, RK_S32 hor_stride, + RK_S32 pixel_aign, RK_S32 pixel_size, + const char *fmt_name) +{ + if (!workaround && hor_stride != MPP_ALIGN(hor_stride, pixel_aign * pixel_size)) { + mpp_log("warning: vepu only support 8 aligned horizontal stride in pixel for %s with pixel size %d\n", + fmt_name, pixel_size); + mpp_log("set byte stride to %d to match the requirement\n", + MPP_ALIGN(hor_stride, pixel_aign * pixel_size)); + workaround = 1; + } + + return workaround; +} + MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg) { MPP_RET ret = MPP_OK; @@ -383,47 +412,47 @@ MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg) prep->offset_cb = 0; prep->offset_cr = 0; - prep->hor_stride = hor_stride; switch (format & MPP_FRAME_FMT_MASK) { case MPP_FMT_YUV420SP : { - if (!prep->stride_workaround && - hor_stride != MPP_ALIGN(hor_stride, 8)) { - mpp_log_f("vepu only support 8byte aligned YUV420SP horizontal stride %d vs width %d\n", - hor_stride, cfg->width); - prep->stride_workaround = 1; + if (check_8_pixel_aligned(prep->not_8_pixel, hor_stride, 8, 1, "YUV420SP")) { + hor_stride = MPP_ALIGN(hor_stride, 8); + prep->not_8_pixel = 1; } prep->offset_cb = hor_stride * ver_stride; prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); prep->size_c = hor_stride / 2 * MPP_ALIGN(prep->src_h / 2, 8); + prep->pixel_stride = hor_stride; } break; case MPP_FMT_YUV420P : { - if (!prep->stride_workaround && - hor_stride != MPP_ALIGN(hor_stride, 16)) { - mpp_log_f("vepu only support 16byte aligned YUV420P horizontal stride %d vs width %d\n", - hor_stride, cfg->width); - prep->stride_workaround = 1; + if (check_8_pixel_aligned(prep->not_8_pixel, hor_stride, 16, 1, "YUV420P")) { + hor_stride = MPP_ALIGN(hor_stride, 8); + prep->not_8_pixel = 1; } prep->offset_cb = hor_stride * ver_stride; prep->offset_cr = prep->offset_cb + ((hor_stride * ver_stride) / 4); prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); prep->size_c = hor_stride / 2 * MPP_ALIGN(prep->src_h / 2, 8); + prep->pixel_stride = hor_stride; } break; case MPP_FMT_YUV422_YUYV : case MPP_FMT_YUV422_UYVY : { - if (!prep->stride_workaround && - ((hor_stride != MPP_ALIGN(hor_stride, 8 * 2)) || - (hor_stride < cfg->width * 2))) { - mpp_log_f("vepu only support 16bit pixel aligned YUV422 horizontal stride %d vs width %d\n", - hor_stride, cfg->width); - prep->stride_workaround = 1; + if (check_stride_by_pixel(prep->is_pixel_stride, cfg->width, + hor_stride, 2)) { + hor_stride *= 2; + prep->is_pixel_stride = 1; + } + + if (check_8_pixel_aligned(prep->not_8_pixel, hor_stride, 8, 2, "YUV422_interleave")) { + hor_stride = MPP_ALIGN(hor_stride, 16); + prep->not_8_pixel = 1; } prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); prep->size_c = 0; - prep->hor_stride = hor_stride / 2; + prep->pixel_stride = hor_stride / 2; } break; case MPP_FMT_RGB565 : case MPP_FMT_BGR565 : @@ -431,17 +460,20 @@ MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg) case MPP_FMT_BGR555 : case MPP_FMT_RGB444 : case MPP_FMT_BGR444 : { - if (!prep->stride_workaround && - ((hor_stride != MPP_ALIGN(hor_stride, 8 * 2)) || - (hor_stride < cfg->width * 2))) { - mpp_log_f("vepu only support matched 16bit pixel horizontal stride %d vs width %d\n", - hor_stride, cfg->width); - prep->stride_workaround = 1; + if (check_stride_by_pixel(prep->is_pixel_stride, cfg->width, + hor_stride, 2)) { + hor_stride *= 2; + prep->is_pixel_stride = 1; + } + + if (check_8_pixel_aligned(prep->not_8_pixel, hor_stride, 8, 2, "32bit RGB")) { + hor_stride = MPP_ALIGN(hor_stride, 16); + prep->not_8_pixel = 1; } prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); prep->size_c = 0; - prep->hor_stride = hor_stride / 2; + prep->pixel_stride = hor_stride / 2; } break; case MPP_FMT_ARGB8888 : case MPP_FMT_ABGR8888 : @@ -449,17 +481,20 @@ MPP_RET h264e_vepu_prep_setup(HalH264eVepuPrep *prep, MppEncPrepCfg *cfg) case MPP_FMT_BGRA8888 : case MPP_FMT_RGB101010 : case MPP_FMT_BGR101010 : { - if (!prep->stride_workaround && - ((hor_stride == MPP_ALIGN(hor_stride, 8 * 4)) || - (hor_stride < cfg->width * 4))) { - mpp_log_f("vepu only support matched 32bit pixel horizontal stride %d vs width %d\n", - hor_stride, cfg->width); - prep->stride_workaround = 1; + if (check_stride_by_pixel(prep->is_pixel_stride, cfg->width, + hor_stride, 4)) { + hor_stride *= 4; + prep->is_pixel_stride = 1; + } + + if (check_8_pixel_aligned(prep->not_8_pixel, hor_stride, 8, 4, "16bit RGB")) { + hor_stride = MPP_ALIGN(hor_stride, 32); + prep->not_8_pixel = 1; } prep->size_y = hor_stride * MPP_ALIGN(prep->src_h, 16); prep->size_c = 0; - prep->hor_stride = hor_stride / 4; + prep->pixel_stride = hor_stride / 4; } break; default: { mpp_err_f("invalid format %d", format); diff --git a/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.h b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.h index 132ed8bc..6ece7660 100644 --- a/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.h +++ b/mpp/hal/vpu/h264e/hal_h264e_vepu_v2.h @@ -41,7 +41,7 @@ typedef struct HalH264eVepuInput_t { RK_S32 src_fmt; RK_S32 src_w; RK_S32 src_h; - RK_S32 hor_stride; + RK_S32 pixel_stride; size_t size_y; size_t size_c; @@ -49,7 +49,8 @@ typedef struct HalH264eVepuInput_t { RK_U32 offset_cb; RK_U32 offset_cr; - RK_U16 stride_workaround; + RK_U8 not_8_pixel; + RK_U8 is_pixel_stride; RK_U8 r_mask_msb; RK_U8 g_mask_msb; diff --git a/utils/mpi_enc_utils.c b/utils/mpi_enc_utils.c index bc8fc5b9..4a411fc3 100644 --- a/utils/mpi_enc_utils.c +++ b/utils/mpi_enc_utils.c @@ -41,7 +41,10 @@ RK_S32 mpi_enc_width_default_stride(RK_S32 width, MppFrameFormat fmt) stride = MPP_ALIGN(width, 16); } break; case MPP_FMT_YUV422P: - case MPP_FMT_YUV422SP: + case MPP_FMT_YUV422SP: { + /* NOTE: 422 need to align to 8 so chroma can align to 16 */ + stride = MPP_ALIGN(width, 8); + } break; case MPP_FMT_RGB565: case MPP_FMT_BGR565: case MPP_FMT_RGB555: @@ -60,10 +63,12 @@ RK_S32 mpi_enc_width_default_stride(RK_S32 width, MppFrameFormat fmt) /* NOTE: for vepu limitation */ stride = MPP_ALIGN(width, 8) * 3; } break; + case MPP_FMT_RGB101010 : + case MPP_FMT_BGR101010 : case MPP_FMT_ARGB8888 : - case MPP_FMT_ABGR8888: - case MPP_FMT_BGRA8888: - case MPP_FMT_RGBA8888: { + case MPP_FMT_ABGR8888 : + case MPP_FMT_BGRA8888 : + case MPP_FMT_RGBA8888 : { /* NOTE: for vepu limitation */ stride = MPP_ALIGN(width, 8) * 4; } break; diff --git a/utils/utils.c b/utils/utils.c index bbef5f23..9aebb129 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -422,6 +422,146 @@ err: return ret; } +static void fill_MPP_FMT_RGB565(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U16 val = ((R >> 3) & 0x1f) | (((G >> 2) & 0x3f) << 5) | (((B >> 3) & 0x1f) << 11); + p[0] = (val >> 8) & 0xff; + p[1] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_BGR565(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U16 val = ((B >> 3) & 0x1f) | (((G >> 2) & 0x3f) << 5) | (((R >> 3) & 0x1f) << 11); + p[0] = (val >> 8) & 0xff; + p[1] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_RGB555(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U16 val = ((R >> 3) & 0x1f) | (((G >> 3) & 0x1f) << 5) | (((B >> 3) & 0x1f) << 10); + p[0] = (val >> 8) & 0xff; + p[1] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_BGR555(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U16 val = ((B >> 3) & 0x1f) | (((G >> 3) & 0x1f) << 5) | (((R >> 3) & 0x1f) << 10); + p[0] = (val >> 8) & 0xff; + p[1] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_RGB444(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U16 val = ((R >> 4) & 0xf) | (((G >> 4) & 0xf) << 4) | (((B >> 4) & 0xf) << 8); + p[0] = (val >> 8) & 0xff; + p[1] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_BGR444(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U16 val = ((B >> 4) & 0xf) | (((G >> 4) & 0xf) << 4) | (((R >> 4) & 0xf) << 8); + p[0] = (val >> 8) & 0xff; + p[1] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_RGB101010(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U32 val = ((R * 4) & 0x3ff) | (((G * 4) & 0x3ff) << 10) | (((B * 4) & 0x3ff) << 20); + p[0] = (val >> 24) & 0xff; + p[1] = (val >> 16) & 0xff; + p[2] = (val >> 8) & 0xff; + p[3] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_BGR101010(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + RK_U32 val = ((B * 4) & 0x3ff) | (((G * 4) & 0x3ff) << 10) | (((R * 4) & 0x3ff) << 20); + p[0] = (val >> 24) & 0xff; + p[1] = (val >> 16) & 0xff; + p[2] = (val >> 8) & 0xff; + p[3] = (val >> 0) & 0xff; +} + +static void fill_MPP_FMT_ARGB8888(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + p[0] = 0xff; + p[1] = R; + p[2] = G; + p[3] = B; +} + +static void fill_MPP_FMT_ABGR8888(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + p[0] = 0xff; + p[1] = B; + p[2] = G; + p[3] = R; +} + +static void fill_MPP_FMT_BGRA8888(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + p[0] = B; + p[1] = G; + p[2] = R; + p[3] = 0xff; +} + +static void fill_MPP_FMT_RGBA8888(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B) +{ + p[0] = R; + p[1] = G; + p[2] = B; + p[3] = 0xff; +} + +typedef void (*FillRgbFunc)(RK_U8 *p, RK_U32 R, RK_U32 G, RK_U32 B); + +FillRgbFunc fill_rgb_funcs[] = { + fill_MPP_FMT_RGB565, + fill_MPP_FMT_BGR565, + fill_MPP_FMT_RGB555, + fill_MPP_FMT_BGR555, + fill_MPP_FMT_RGB444, + fill_MPP_FMT_BGR444, + NULL, + NULL, + fill_MPP_FMT_RGB101010, + fill_MPP_FMT_BGR101010, + fill_MPP_FMT_ARGB8888, + fill_MPP_FMT_ABGR8888, + fill_MPP_FMT_BGRA8888, + fill_MPP_FMT_RGBA8888, +}; + +static RK_S32 util_check_stride_by_pixel(RK_S32 workaround, RK_S32 width, + RK_S32 hor_stride, RK_S32 pixel_size) +{ + if (!workaround && hor_stride < width * pixel_size) { + mpp_log("warning: stride by bytes %d is smarller than width %d mutiple by pixel size %d\n", + hor_stride, width, pixel_size); + mpp_log("multiple stride %d by pixel size %d and set new byte stride to %d\n", + hor_stride, pixel_size, hor_stride * pixel_size); + workaround = 1; + } + + return workaround; +} + +static RK_S32 util_check_8_pixel_aligned(RK_S32 workaround, RK_S32 hor_stride, + RK_S32 pixel_aign, RK_S32 pixel_size, + const char *fmt_name) +{ + if (!workaround && hor_stride != MPP_ALIGN(hor_stride, pixel_aign * pixel_size)) { + mpp_log("warning: vepu only support 8 aligned horizontal stride in pixel for %s with pixel size %d\n", + fmt_name, pixel_size); + mpp_log("set byte stride to %d to match the requirement\n", + MPP_ALIGN(hor_stride, pixel_aign * pixel_size)); + workaround = 1; + } + + return workaround; +} + MPP_RET fill_image(RK_U8 *buf, RK_U32 width, RK_U32 height, RK_U32 hor_stride, RK_U32 ver_stride, MppFrameFormat fmt, RK_U32 frame_count) @@ -430,6 +570,8 @@ MPP_RET fill_image(RK_U8 *buf, RK_U32 width, RK_U32 height, RK_U8 *buf_y = buf; RK_U8 *buf_c = buf + hor_stride * ver_stride; RK_U32 x, y, i; + static RK_S32 is_pixel_stride = 0; + static RK_S32 not_8_pixel = 0; switch (fmt) { case MPP_FMT_YUV420SP : { @@ -484,50 +626,81 @@ MPP_RET fill_image(RK_U8 *buf, RK_U32 width, RK_U32 height, } } } break; - case MPP_FMT_RGB888 : - case MPP_FMT_BGR888 : { + case MPP_FMT_RGB565 : + case MPP_FMT_BGR565 : + case MPP_FMT_RGB555 : + case MPP_FMT_BGR555 : + case MPP_FMT_RGB444 : + case MPP_FMT_BGR444 : { RK_U8 *p = buf_y; - RK_U32 pix_w = 3; + RK_U32 pix_w = 2; + FillRgbFunc fill = fill_rgb_funcs[fmt - MPP_FRAME_FMT_RGB]; - if (hor_stride < width * pix_w) { - mpp_err_f("invalid %dbit color config: hor_stride %d is smaller then width %d multiply by 4\n", - 8 * pix_w, hor_stride, width, pix_w); - mpp_err_f("width should be defined by pixel count\n"); - mpp_err_f("stride should be defined by byte count\n"); + if (util_check_stride_by_pixel(is_pixel_stride, width, hor_stride, pix_w)) { + hor_stride *= pix_w; + is_pixel_stride = 1; + } - hor_stride = width * pix_w; + if (util_check_8_pixel_aligned(not_8_pixel, hor_stride, + 8, 2, "16bit RGB")) { + hor_stride = MPP_ALIGN(hor_stride, 16); + not_8_pixel = 1; } for (y = 0; y < height; y++, p += hor_stride) { - for (x = 0, i = 0; x < width * pix_w; x += pix_w, i++) { - p[x + 0] = i + y + frame_count * 3; - p[x + 1] = 128 + i + frame_count * 2; - p[x + 2] = 64 + i + frame_count * 5; + for (x = 0, i = 0; x < width; x++, i += pix_w) { + RK_U8 Y = (0 + x + y + frame_count * 3); + RK_U8 U = (128 + (y / 2) + frame_count * 2); + RK_U8 V = (64 + (x / 2) + frame_count * 5); + + RK_S32 R = Y + ((360 * (V - 128)) >> 8); + RK_S32 G = Y - (((88 * (U - 128) + 184 * (V - 128))) >> 8); + RK_S32 B = Y + ((455 * (U - 128)) >> 8); + + R = MPP_CLIP3(0, 255, R); + G = MPP_CLIP3(0, 255, G); + B = MPP_CLIP3(0, 255, B); + + fill(p + i, R, G, B); } } } break; + case MPP_FMT_RGB101010 : + case MPP_FMT_BGR101010 : case MPP_FMT_ARGB8888 : case MPP_FMT_ABGR8888 : case MPP_FMT_BGRA8888 : case MPP_FMT_RGBA8888 : { RK_U8 *p = buf_y; RK_U32 pix_w = 4; + FillRgbFunc fill = fill_rgb_funcs[fmt - MPP_FRAME_FMT_RGB]; - if (hor_stride < width * pix_w) { - mpp_err_f("invalid %dbit color config: hor_stride %d is smaller then width %d multiply by 4\n", - 8 * pix_w, hor_stride, width, pix_w); - mpp_err_f("width should be defined by pixel count\n"); - mpp_err_f("stride should be defined by byte count\n"); + if (util_check_stride_by_pixel(is_pixel_stride, width, hor_stride, pix_w)) { + hor_stride *= pix_w; + is_pixel_stride = 1; + } - hor_stride = width * pix_w; + if (util_check_8_pixel_aligned(not_8_pixel, hor_stride, + 8, 4, "32bit RGB")) { + hor_stride = MPP_ALIGN(hor_stride, 32); + not_8_pixel = 1; } for (y = 0; y < height; y++, p += hor_stride) { - for (x = 0, i = 0; x < width * pix_w; x += pix_w, i++) { - p[x + 0] = i + y + frame_count * 3; - p[x + 1] = 128 + i + frame_count * 2; - p[x + 2] = 64 + i + frame_count * 5; - p[x + 3] = i + y / 2 + frame_count * 3; + for (x = 0, i = 0; x < width; x++, i += pix_w) { + RK_U8 Y = (0 + x + y + frame_count * 3); + RK_U8 U = (128 + (y / 2) + frame_count * 2); + RK_U8 V = (64 + (x / 2) + frame_count * 5); + + RK_S32 R = Y + ((360 * (V - 128)) >> 8); + RK_S32 G = Y - (((88 * (U - 128) + 184 * (V - 128))) >> 8); + RK_S32 B = Y + ((455 * (U - 128)) >> 8); + + R = MPP_CLIP3(0, 255, R); + G = MPP_CLIP3(0, 255, G); + B = MPP_CLIP3(0, 255, B); + + fill(p + i, R, G, B); } } } break;