Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convert: add rfc4175_422be10_to_yuv420p8 #712

Merged
merged 1 commit into from
Jan 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions include/st_convert_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,31 @@ static inline int st20_rfc4175_422be10_to_yuv422p8(struct st20_rfc4175_422_10_pg
return st20_rfc4175_422be10_to_yuv422p8_simd(pg, y, b, r, w, h, MTL_SIMD_LEVEL_MAX);
}

/**
* Convert rfc4175_422be10 to yuv420p8 with the max optimized SIMD level.
*
* @param pg
* Point to pg(rfc4175_422be10) data.
* @param y
* Point to Y(yuv420p8) vector.
* @param b
* Point to b(yuv420p8) vector.
* @param r
* Point to r(yuv420p8) vector.
* @param w
* The st2110-20(video) width.
* @param h
* The st2110-20(video) height.
* @return
* - 0 if successful.
* - <0: Error code if convert fail.
*/
static inline int st20_rfc4175_422be10_to_yuv420p8(struct st20_rfc4175_422_10_pg2_be* pg,
uint8_t* y, uint8_t* b, uint8_t* r,
uint32_t w, uint32_t h) {
return st20_rfc4175_422be10_to_yuv420p8_simd(pg, y, b, r, w, h, MTL_SIMD_LEVEL_MAX);
}

/**
* Convert rfc4175_422be12 to yuv422p12le with the max optimized SIMD level.
*
Expand Down
26 changes: 26 additions & 0 deletions include/st_convert_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,32 @@ int st20_rfc4175_422be10_to_yuv422p8_simd(struct st20_rfc4175_422_10_pg2_be* pg,
uint8_t* y, uint8_t* b, uint8_t* r, uint32_t w,
uint32_t h, enum mtl_simd_level level);

/**
* Convert rfc4175_422be10 to yuv420p8 with required SIMD level.
* Note the level may downgrade to the SIMD which system really support.
*
* @param pg
* Point to pg(rfc4175_422be10) data.
* @param y
* Point to Y(yuv420p8) vector.
* @param b
* Point to b(yuv420p8) vector.
* @param r
* Point to r(yuv420p8) vector.
* @param w
* The st2110-20(video) width.
* @param h
* The st2110-20(video) height.
* @param level
* simd level.
* @return
* - 0 if successful.
* - <0: Error code if convert fail.
*/
int st20_rfc4175_422be10_to_yuv420p8_simd(struct st20_rfc4175_422_10_pg2_be* pg,
uint8_t* y, uint8_t* b, uint8_t* r, uint32_t w,
uint32_t h, enum mtl_simd_level level);

/**
* Convert rfc4175_422be12 to yuv422p12le with required SIMD level.
* Note the level may downgrade to the SIMD which system really support.
Expand Down
2 changes: 2 additions & 0 deletions include/st_pipeline_api.h
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ enum st_frame_fmt {
* transport frame without conversion. The frame should not have lines padding.
*/
ST_FRAME_FMT_YUV422CUSTOM8 = 13,
/** YUV 420 planar 8bit */
ST_FRAME_FMT_YUV420PLANAR8 = 14,
/** End of yuv format list, new yuv should be inserted before this */
ST_FRAME_FMT_YUV_END,

Expand Down
8 changes: 8 additions & 0 deletions lib/src/st2110/pipeline/st20_pipeline_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,14 @@ static int rx_st20p_packet_convert(void* priv, void* frame,
uint8_t* r = (uint8_t*)framebuff->dst.addr[2] +
framebuff->dst.linesize[2] * meta->row_number + meta->row_offset;
ret = st20_rfc4175_422be10_to_yuv422p8(src, y, b, r, meta->pg_cnt, 2);
} else if (ctx->ops.output_fmt == ST_FRAME_FMT_YUV420PLANAR8) {
uint8_t* y = (uint8_t*)framebuff->dst.addr[0] +
framebuff->dst.linesize[0] * meta->row_number + meta->row_offset * 2;
uint8_t* b = (uint8_t*)framebuff->dst.addr[1] +
framebuff->dst.linesize[1] * meta->row_number + meta->row_offset;
uint8_t* r = (uint8_t*)framebuff->dst.addr[2] +
framebuff->dst.linesize[2] * meta->row_number + meta->row_offset;
ret = st20_rfc4175_422be10_to_yuv420p8(src, y, b, r, meta->pg_cnt, 2);
}

return ret;
Expand Down
71 changes: 71 additions & 0 deletions lib/src/st2110/st_convert.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,33 @@ static int convert_rfc4175_422be10_to_yuv422p8(struct st_frame* src,
return ret;
}

static int convert_rfc4175_422be10_to_yuv420p8(struct st_frame* src,
struct st_frame* dst) {
int ret = 0;
struct st20_rfc4175_422_10_pg2_be* be10 = NULL;
uint8_t* y = NULL;
uint8_t* b = NULL;
uint8_t* r = NULL;
uint32_t h = st_frame_data_height(dst);

if (!has_lines_padding(src, dst)) {
be10 = src->addr[0];
y = dst->addr[0];
b = dst->addr[1];
r = dst->addr[2];
ret = st20_rfc4175_422be10_to_yuv420p8(be10, y, b, r, dst->width, h);
} else {
for (uint32_t line = 0; line < h; line++) {
be10 = src->addr[0] + src->linesize[0] * line;
y = dst->addr[0] + dst->linesize[0] * line;
b = dst->addr[1] + dst->linesize[1] * line;
r = dst->addr[2] + dst->linesize[2] * line;
ret = st20_rfc4175_422be10_to_yuv420p8(be10, y, b, r, dst->width, 1);
}
}
return ret;
}

static int convert_rfc4175_422be10_to_v210(struct st_frame* src, struct st_frame* dst) {
int ret = 0;
struct st20_rfc4175_422_10_pg2_be* be10 = NULL;
Expand Down Expand Up @@ -504,6 +531,11 @@ static const struct st_frame_converter converters[] = {
.dst_fmt = ST_FRAME_FMT_YUV422PLANAR8,
.convert_func = convert_rfc4175_422be10_to_yuv422p8,
},
{
.src_fmt = ST_FRAME_FMT_YUV422RFC4175PG2BE10,
.dst_fmt = ST_FRAME_FMT_YUV420PLANAR8,
.convert_func = convert_rfc4175_422be10_to_yuv420p8,
},
{
.src_fmt = ST_FRAME_FMT_YUV422RFC4175PG2BE10,
.dst_fmt = ST_FRAME_FMT_V210,
Expand Down Expand Up @@ -1329,6 +1361,45 @@ int st20_rfc4175_422be10_to_yuv422p8_simd(struct st20_rfc4175_422_10_pg2_be* pg,
return st20_rfc4175_422be10_to_yuv422p8_scalar(pg, y, b, r, w, h);
}

static int st20_rfc4175_422be10_to_yuv420p8_scalar(struct st20_rfc4175_422_10_pg2_be* pg,
uint8_t* y, uint8_t* b, uint8_t* r,
uint32_t w, uint32_t h) {
uint32_t line_pg_cnt = w / 2; /* two pgs in one convert */

for (uint32_t i = 0; i < (h / 2); i++) { /* 2 lines each loop */
/* first line */
for (uint32_t j = 0; j < line_pg_cnt; j++) {
*b++ = pg->Cb00;
*y++ = (pg->Y00 << 2) | (pg->Y00_ >> 2);
*r++ = (pg->Cr00 << 4) | (pg->Cr00_ >> 2);
*y++ = (pg->Y01 << 6) | (pg->Y01_ >> 2);
pg++;
}
/* second line, no u and v */
for (uint32_t j = 0; j < line_pg_cnt; j++) {
*y++ = (pg->Y00 << 2) | (pg->Y00_ >> 2);
*y++ = (pg->Y01 << 6) | (pg->Y01_ >> 2);
pg++;
}
}

return 0;
}

int st20_rfc4175_422be10_to_yuv420p8_simd(struct st20_rfc4175_422_10_pg2_be* pg,
uint8_t* y, uint8_t* b, uint8_t* r, uint32_t w,
uint32_t h, enum mtl_simd_level level) {
enum mtl_simd_level cpu_level = mtl_get_simd_level();
int ret;

MTL_MAY_UNUSED(cpu_level);
MTL_MAY_UNUSED(level);
MTL_MAY_UNUSED(ret);

/* the last option */
return st20_rfc4175_422be10_to_yuv420p8_scalar(pg, y, b, r, w, h);
}

int st20_rfc4175_422le10_to_v210_scalar(uint8_t* pg_le, uint8_t* pg_v210, uint32_t w,
uint32_t h) {
uint32_t pg_count = w * h / 2;
Expand Down
8 changes: 8 additions & 0 deletions lib/src/st2110/st_fmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,13 @@ static const struct st_frame_fmt_desc st_frame_fmt_descs[] = {
.planes = 1,
.sampling = ST_FRAME_SAMPLING_422,
},
{
/* ST_FRAME_FMT_YUV420PLANAR8 */
.fmt = ST_FRAME_FMT_YUV420PLANAR8,
.name = "YUV420PLANAR8",
.planes = 3,
.sampling = ST_FRAME_SAMPLING_420,
},
{
/* ST_FRAME_FMT_RGBRFC4175PG4BE10 */
.fmt = ST_FRAME_FMT_RGBRFC4175PG4BE10,
Expand Down Expand Up @@ -522,6 +529,7 @@ size_t st_frame_size(enum st_frame_fmt fmt, uint32_t width, uint32_t height,
size = pixels * 3; /* 8 bits RGB pixel in a 24 bits */
break;
case ST_FRAME_FMT_YUV420CUSTOM8:
case ST_FRAME_FMT_YUV420PLANAR8:
size = st20_frame_size(ST20_FMT_YUV_420_8BIT, width, height);
break;
default:
Expand Down
65 changes: 65 additions & 0 deletions python/example/misc_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,19 @@ def ptr_to_yuv422p8(ptr, width, height):
return y, u, v


def ptr_to_yuv420p8(ptr, width, height):
y_size = width * height
u_size = width * height // 4

frame = np.frombuffer(ptr, dtype=np.uint8)

y = frame[:y_size].reshape((height, width))
u = frame[y_size : y_size + u_size].reshape((height // 2, width // 2))
v = frame[y_size + u_size :].reshape((height // 2, width // 2))

return y, u, v


def yuv422p10le_to_yuv422(ptr, width, height):
y_size = width * height
u_size = width * height // 2
Expand Down Expand Up @@ -170,6 +183,28 @@ def downscale_yuv422(y, u, v, scale_factor):
return y_downscaled, u_downscaled, v_downscaled


def downscale_yuv420(y, u, v, scale_factor):
height, width = y.shape

y_downscaled = cv2.resize(
y,
(width // scale_factor, height // scale_factor),
interpolation=cv2.INTER_LINEAR,
)
u_downscaled = cv2.resize(
u,
(width // (2 * scale_factor), height // (2 * scale_factor)),
interpolation=cv2.INTER_LINEAR,
)
v_downscaled = cv2.resize(
v,
(width // (2 * scale_factor), height // (2 * scale_factor)),
interpolation=cv2.INTER_LINEAR,
)

return y_downscaled, u_downscaled, v_downscaled


def display_yuv422(y, u, v):
u = cv2.resize(u, (y.shape[1], y.shape[0]), interpolation=cv2.INTER_LINEAR)
v = cv2.resize(v, (y.shape[1], y.shape[0]), interpolation=cv2.INTER_LINEAR)
Expand All @@ -180,6 +215,18 @@ def display_yuv422(y, u, v):
cv2.waitKey(1)


def display_yuv420(y, u, v):
u = cv2.resize(u, (y.shape[1], y.shape[0]), interpolation=cv2.INTER_LINEAR)
v = cv2.resize(v, (y.shape[1], y.shape[0]), interpolation=cv2.INTER_LINEAR)

yuv = cv2.merge([y, u, v])

# display_img = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR_I420)
display_img = cv2.cvtColor(yuv, cv2.COLOR_YUV2BGR)
cv2.imshow(sys.argv[0], display_img)
cv2.waitKey(1)


def destroy():
cv2.destroyAllWindows()

Expand All @@ -200,6 +247,22 @@ def frame_display_yuv422p8(frame, display_scale_factor):
display_yuv422(y_scale, u_scale, v_scale)


def frame_display_yuv420p8(frame, display_scale_factor):
# Pack frame pointer from frame addr
ptr = (ctypes.c_ubyte * (frame.data_size)).from_address(
mtl.st_frame_addr_cpuva(frame, 0)
)
width = frame.width
height = frame.height

# Convert to yuv420 planar 8
y, u, v = ptr_to_yuv420p8(ptr, width, height)
# Downscale
y_scale, u_scale, v_scale = downscale_yuv420(y, u, v, display_scale_factor)
# Convert to RGB and display
display_yuv420(y_scale, u_scale, v_scale)


def frame_display_yuv422p10le(frame, display_scale_factor):
# Pack frame pointer from frame addr
ptr = (ctypes.c_ubyte * (frame.data_size)).from_address(
Expand Down Expand Up @@ -259,6 +322,8 @@ def frame_display(mtl_handle, frame, display_scale_factor):
frame_display_yuv422p8(frame, display_scale_factor)
elif frame.fmt == mtl.ST_FRAME_FMT_YUV422RFC4175PG2BE10:
frame_display_rfc4175be10(mtl_handle, frame, display_scale_factor)
elif frame.fmt == mtl.ST_FRAME_FMT_YUV420PLANAR8:
frame_display_yuv420p8(frame, display_scale_factor)
else:
print(f"Unknown fmt: {mtl.st_frame_fmt_name(frame.fmt)}")

Expand Down