[hal_h264e_vepu]: Fix stride parameter compatible

Fix stride definition to compatible to both pixel stride and byte
stride.

In MPI the stride is defined to byte stride. But vepu requires 8 pixel
aligned pixel stride.

So we add more code to adapt to both case and check 8 pixel alignment.

From opengles definition:

Stride means bytes in a row of pixels including padding. So an image
could be 510 pixels in width and rounded up to 512 pixels. The stride
would be 512 * bit depth of the image's format. You could also have
stride in pixels in which case the stride would be 512 pixels

Pitch is a little more vague, but typically could be interchangeable
with stride. Considering your reference is specifying in bytes, it's
likely safe to assume they're not measuring in pixels. So the reference
likely means the number of bytes in a row + padding, the only
alternative would be number of bytes without padding e.g. image width *
bit depth.

Change-Id: I20acf71e2a6bea2eb08b41fe7df531154ebef897
Signed-off-by: Herman Chen <herman.chen@rock-chips.com>
This commit is contained in:
Herman Chen
2020-09-23 15:27:26 +08:00
parent 7987b57bd1
commit 16ba8b5820
6 changed files with 278 additions and 64 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -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);

View File

@@ -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;

View File

@@ -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,6 +63,8 @@ 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 :

View File

@@ -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;