Skip to content
Draft
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
321 changes: 6 additions & 315 deletions include/upipe/ubuf_pic.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,279 +358,20 @@ static inline int ubuf_pic_resize(struct ubuf *ubuf, int hskip, int vskip,
* their alpha value is more than this value
* @return an error code
*/
static inline int ubuf_pic_blit_alpha(struct ubuf *dest, struct ubuf *src,
int ubuf_pic_blit_alpha(struct ubuf *dest, struct ubuf *src,
int dest_hoffset, int dest_voffset,
int src_hoffset, int src_voffset,
int extract_hsize, int extract_vsize,
const uint8_t *alpha_plane, int alpha_stride,
const int alpha, const int threshold)
{
if (alpha_plane == NULL && alpha < threshold && threshold != 0xff)
return UBASE_ERR_NONE; /* nothing to do */

uint8_t src_macropixel;
UBASE_RETURN(ubuf_pic_size(src, NULL, NULL, &src_macropixel))
uint8_t dest_macropixel;
UBASE_RETURN(ubuf_pic_size(dest, NULL, NULL, &dest_macropixel))
if (unlikely(dest_macropixel != src_macropixel))
return UBASE_ERR_INVALID;

#define MAX_PLANES 3

const char *chroma;
ubuf_pic_foreach_plane(dest, chroma) {
const char *in_chroma[MAX_PLANES] = { chroma };
unsigned in_planes = 1;
int err;

size_t dest_stride;
uint8_t dest_hsub, dest_vsub, dest_macropixel_size;
UBASE_RETURN(ubuf_pic_plane_size(dest, chroma,
&dest_stride, &dest_hsub, &dest_vsub,
&dest_macropixel_size))

size_t src_stride;
uint8_t src_hsub, src_vsub, src_macropixel_size;
err = ubuf_pic_plane_size(src, in_chroma[0], &src_stride, &src_hsub,
&src_vsub, &src_macropixel_size);
if (!ubase_check(err)) {
if (!strcmp(chroma, "u8v8")) {
in_chroma[0] = "u8";
in_chroma[1] = "v8";
in_planes = 2;
} else
return err;

for (unsigned i = 0; i < in_planes; i++) {
UBASE_RETURN(ubuf_pic_plane_size(src, in_chroma[i], &src_stride,
&src_hsub, &src_vsub,
&src_macropixel_size));
if (unlikely(src_hsub != dest_hsub || src_vsub != dest_vsub ||
src_macropixel_size !=
dest_macropixel_size / in_planes))
return UBASE_ERR_INVALID;
}
} else if (unlikely(src_hsub != dest_hsub || src_vsub != dest_vsub ||
src_macropixel_size != dest_macropixel_size))
return UBASE_ERR_INVALID;

uint8_t *dest_buffer;
const uint8_t *in[MAX_PLANES];
UBASE_RETURN(ubuf_pic_plane_write(dest, chroma,
dest_hoffset, dest_voffset,
extract_hsize, extract_vsize, &dest_buffer))
for (unsigned i = 0; i < in_planes; i++) {
err =
ubuf_pic_plane_read(src, in_chroma[i], src_hoffset, src_voffset,
extract_hsize, extract_vsize, &in[i]);
if (unlikely(!ubase_check(err))) {
for (; i; i--)
ubuf_pic_plane_unmap(src, in_chroma[i - 1], src_hoffset,
src_voffset, extract_hsize,
extract_vsize);
ubuf_pic_plane_unmap(dest, chroma, dest_hoffset, dest_voffset,
extract_hsize, extract_vsize);
return err;
}
}

int plane_hsize = extract_hsize / src_hsub / src_macropixel *
src_macropixel_size;
int plane_vsize = extract_vsize / src_vsub;

for (int i = 0; i < plane_vsize; i++) {
if ((!alpha_plane && alpha == 0xff) || threshold == 0) {
if (in_planes == 1)
memcpy(dest_buffer, in[0], plane_hsize);
else {
for (int j = 0; j < plane_hsize; j++) {
for (int p = 0; p < in_planes; p++)
dest_buffer[j * in_planes + p] =
(dest_buffer[j * in_planes + p] *
(0xff - alpha) +
in[p][j] * alpha) /
0xff;
}
}
} else if (!alpha_plane) {
for (int j = 0; j < plane_hsize; j++) {
for (int p = 0; p < in_planes; p++)
dest_buffer[j * in_planes + p] =
(dest_buffer[j * in_planes + p] * (0xff - alpha) +
in[p][j] * alpha) /
0xff;
}
} else if (threshold != 0xff) {
/* This is an on/off blending
* if alpha is over the threshold, we use the subpicture pixel.
*/
if (alpha == 0xff) {
for (int j = 0; j < plane_hsize; j++) {
const uint8_t a = alpha_plane[alpha_stride * (i * src_vsub) + j * src_hsub];
if (a > threshold) {
for (int p = 0; p < in_planes; p++)
dest_buffer[j * in_planes + p] = in[p][j];
}
}
} else {
for (int j = 0; j < plane_hsize; j++) {
const uint8_t a = (uint16_t)alpha_plane[alpha_stride * (i * src_vsub) + j * src_hsub] * (uint16_t)alpha / 0xff;
if (a > threshold) {
for (int p = 0; p < in_planes; p++)
dest_buffer[j * in_planes + p] = in[p][j];
}
}
}
} else {
/* smooth and slow blending */
if (alpha == 0xff) {
for (int j = 0; j < plane_hsize; j++) {
const uint8_t a = alpha_plane[alpha_stride * (i * src_vsub) + j * src_hsub];
for (int p = 0; p < in_planes; p++)
dest_buffer[j * in_planes + p] =
(dest_buffer[j * in_planes + p] * (0xff - a) +
in[p][j] * a) /
0xff;
}
} else {
for (int j = 0; j < plane_hsize; j++) {
const uint8_t a = (uint16_t)alpha_plane[alpha_stride * (i * src_vsub) + j * src_hsub] * (uint16_t)alpha / 0xff;
for (int p = 0; p < in_planes; p++)
dest_buffer[j * in_planes + p] =
(dest_buffer[j * in_planes + p] * (0xff - a) +
in[p][j] * a) /
0xff;
}
}
}
dest_buffer += dest_stride;
for (int p = 0; p < in_planes; p++)
in[p] += src_stride;
}

err = ubuf_pic_plane_unmap(dest, chroma,
dest_hoffset, dest_voffset,
extract_hsize, extract_vsize);
for (int p = 0; p < in_planes; p++)
UBASE_RETURN(ubuf_pic_plane_unmap(src, in_chroma[p], src_hoffset,
src_voffset, extract_hsize,
extract_vsize))
UBASE_RETURN(err)
}

#undef MAX_PLANES

return UBASE_ERR_NONE;
}
const int alpha, const int threshold);

/** @see ubuf_pic_blit_alpha */
static inline int ubuf_pic_blit_alpha10(struct ubuf *dest, struct ubuf *src,
int ubuf_pic_blit_alpha10(struct ubuf *dest, struct ubuf *src,
int dest_hoffset, int dest_voffset,
int src_hoffset, int src_voffset,
int extract_hsize, int extract_vsize,
const uint8_t *alpha_plane, int alpha_stride,
const int alpha, const int threshold)
{
if (alpha_plane == NULL && alpha < threshold && threshold != 0x3ff)
return UBASE_ERR_NONE; /* nothing to do */

uint8_t src_macropixel;
UBASE_RETURN(ubuf_pic_size(src, NULL, NULL, &src_macropixel))
uint8_t dest_macropixel;
UBASE_RETURN(ubuf_pic_size(dest, NULL, NULL, &dest_macropixel))
if (unlikely(dest_macropixel != src_macropixel))
return UBASE_ERR_INVALID;

const char *chroma;
ubuf_pic_foreach_plane(dest, chroma) {
size_t src_stride;
uint8_t src_hsub, src_vsub, src_macropixel_size;
UBASE_RETURN(ubuf_pic_plane_size(src, chroma, &src_stride,
&src_hsub, &src_vsub, &src_macropixel_size))

size_t dest_stride;
uint8_t dest_hsub, dest_vsub, dest_macropixel_size;
UBASE_RETURN(ubuf_pic_plane_size(dest, chroma,
&dest_stride, &dest_hsub, &dest_vsub,
&dest_macropixel_size))

if (unlikely(src_hsub != dest_hsub || src_vsub != dest_vsub ||
src_macropixel_size != dest_macropixel_size))
return UBASE_ERR_INVALID;

uint8_t *dest_buffer;
const uint8_t *src_buffer;
UBASE_RETURN(ubuf_pic_plane_write(dest, chroma,
dest_hoffset, dest_voffset,
extract_hsize, extract_vsize, &dest_buffer))
int err = ubuf_pic_plane_read(src, chroma, src_hoffset, src_voffset,
extract_hsize, extract_vsize,
&src_buffer);
if (unlikely(!ubase_check(err))) {
ubuf_pic_plane_unmap(dest, chroma,
dest_hoffset, dest_voffset,
extract_hsize, extract_vsize);
return err;
}

int plane_hsize = extract_hsize / src_hsub / src_macropixel *
src_macropixel_size;
int plane_vsize = extract_vsize / src_vsub;

for (int i = 0; i < plane_vsize; i++) {
uint16_t *real_dst = (uint16_t *)dest_buffer;
const uint16_t *real_src = (const uint16_t *)src_buffer;
const uint16_t *real_alpha = (const uint16_t *)(alpha_plane + alpha_stride * i * src_vsub);

if ((!alpha_plane && alpha == 0x3ff) || threshold == 0) {
memcpy(dest_buffer, src_buffer, plane_hsize);
} else if (!alpha_plane) {
for (int j = 0; j < plane_hsize/2; j++) {
real_dst[j] = (real_dst[j] * (0x3ff - alpha) + real_src[j] * alpha) / 0x3ff;
}
} else if (threshold != 0x3ff) {
/* This is an on/off blending
* if alpha is over the threshold, we use the subpicture pixel.
*/
if (alpha == 0x3ff) {
for (int j = 0; j < plane_hsize/2; j++) {
const uint16_t a = real_alpha[j * src_hsub];
if (a > threshold) real_dst[j] = real_src[j];
}
} else {
for (int j = 0; j < plane_hsize/2; j++) {
const uint16_t a = real_alpha[j * src_hsub] * alpha / 0x3ff;
if (a > threshold) real_dst[j] = real_src[j];
}
}
} else {
/* smooth and slow blending */
if (alpha == 0x3ff) {
for (int j = 0; j < plane_hsize/2; j++) {
const uint16_t a = real_alpha[j * src_hsub];
real_dst[j] = (real_dst[j] * (0x3ff - a) + real_src[j] * a) / 0x3ff;
}
} else {
for (int j = 0; j < plane_hsize/2; j++) {
const uint16_t a = real_alpha[j * src_hsub] * alpha / 0x3ff;
real_dst[j] = (real_dst[j] * (0x3ff - a) + real_src[j] * a) / 0x3ff;
}
}
}
dest_buffer += dest_stride;
src_buffer += src_stride;
}

err = ubuf_pic_plane_unmap(dest, chroma,
dest_hoffset, dest_voffset,
extract_hsize, extract_vsize);
UBASE_RETURN(ubuf_pic_plane_unmap(src, chroma,
src_hoffset, src_voffset,
extract_hsize, extract_vsize))
UBASE_RETURN(err)
}
return UBASE_ERR_NONE;
}
const int alpha, const int threshold);

/** @This blits a picture ubuf to another ubuf.
*
Expand All @@ -648,61 +389,11 @@ static inline int ubuf_pic_blit_alpha10(struct ubuf *dest, struct ubuf *src,
* @param threshold threshold parameter for alpha
* @return an error code
*/
static inline int ubuf_pic_blit(struct ubuf *dest, struct ubuf *src,
int ubuf_pic_blit(struct ubuf *dest, struct ubuf *src,
int dest_hoffset, int dest_voffset,
int src_hoffset, int src_voffset,
int extract_hsize, int extract_vsize,
const int alpha, const int threshold)
{
const uint8_t *alpha_plane = NULL;
size_t alpha_stride = 0;
int ret;

static const char *alpha_plane_names[] = { "a8", "a10l" };
const char *apn;
for (size_t i = 0; i < UBASE_ARRAY_SIZE(alpha_plane_names); i++) {
apn = alpha_plane_names[i];

/* Check for the existence of the given alpha plane. */
ret = ubuf_pic_plane_read(src, apn, 0, 0, -1, -1, &alpha_plane);
/* Continue to the next if it isn't found. */
if (!ubase_check(ret))
continue;

/* Get the stride. */
ret = ubuf_pic_plane_size(src, apn, &alpha_stride, NULL, NULL, NULL);
/* Jump out of the loop if there is an error. */
if (!ubase_check(ret))
goto end;

/* Perform blit. */
if (i == 0)
ret = ubuf_pic_blit_alpha(dest, src, dest_hoffset, dest_voffset,
src_hoffset, src_voffset,
extract_hsize, extract_vsize,
alpha_plane, alpha_stride, alpha, threshold);
else
ret = ubuf_pic_blit_alpha10(dest, src, dest_hoffset, dest_voffset,
src_hoffset, src_voffset,
extract_hsize, extract_vsize,
alpha_plane, alpha_stride, alpha, threshold);

/* Jump out of the loop when it is done. */
goto end;
}

/* Fallback to no alpha plane. */
ret = ubuf_pic_blit_alpha(dest, src, dest_hoffset, dest_voffset,
src_hoffset, src_voffset,
extract_hsize, extract_vsize,
NULL, 0, alpha, threshold);

end:
if (alpha_plane)
ubuf_pic_plane_unmap(src, apn, 0, 0, -1, -1);

return ret;
}
const int alpha, const int threshold);

/** @This copies a picture ubuf to a newly allocated ubuf, and doesn't deal
* with the old ubuf or a dictionary.
Expand Down
1 change: 1 addition & 0 deletions lib/upipe/Build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ libupipe-src = \
ubuf_mem.c \
ubuf_mem_common.c \
ubuf_pic.c \
ubuf_pic_blit_x86.h \
ubuf_pic_common.c \
ubuf_pic_mem.c \
ubuf_sound_common.c \
Expand Down
Loading
Loading