mirror of https://github.com/mpv-player/mpv
spudec.c: crop subs, set scaled flag
Crop subtitle images produced by spudec.c: instead of returning a frame- sized bitmap (with possibly large transparent regions), return a cropped down rectangle of the visible part only. The old spudec scaler code had this as spudec_cut_image(), but it worked on the data converted to the old OSD format only. Move most code to setup the sub-bitmap from spudec_get_indexed() to spudec_process_data(), so that cropping can be done every time a new subtitle is decoded, instead of every frame. Set the sub_bitmaps->scaled flag. Without it, vo_gl and vo_vdpau produced ugly artifacts on the borders.
This commit is contained in:
parent
44c62a6852
commit
84c3480686
114
sub/spudec.c
114
sub/spudec.c
|
@ -125,8 +125,8 @@ typedef struct {
|
||||||
|
|
||||||
struct palette_crop_cache palette_crop_cache;
|
struct palette_crop_cache palette_crop_cache;
|
||||||
|
|
||||||
struct sub_bitmap borrowed_sub_part;
|
|
||||||
struct old_osd_planar borrowed_sub_image;
|
struct old_osd_planar borrowed_sub_image;
|
||||||
|
struct sub_bitmap sub_part, borrowed_sub_part;
|
||||||
struct osd_bmp_indexed borrowed_bmp;
|
struct osd_bmp_indexed borrowed_bmp;
|
||||||
} spudec_handle_t;
|
} spudec_handle_t;
|
||||||
|
|
||||||
|
@ -344,6 +344,70 @@ int spudec_apply_palette_crop(void *this, uint32_t palette,
|
||||||
return c->result;
|
return c->result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void setup_palette(spudec_handle_t *spu, uint32_t palette[256])
|
||||||
|
{
|
||||||
|
memset(palette, 0, sizeof(palette));
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
int alpha = spu->alpha[i];
|
||||||
|
// extend 4 -> 8 bit
|
||||||
|
alpha |= alpha << 4;
|
||||||
|
if (spu->custom && (spu->cuspal[i] >> 31) != 0)
|
||||||
|
alpha = 0;
|
||||||
|
int color = spu->custom ? spu->cuspal[i] :
|
||||||
|
spu->global_palette[spu->palette[i]];
|
||||||
|
int y = (color >> 16) & 0xff;
|
||||||
|
int u = (color >> 8) & 0xff;
|
||||||
|
int v = color & 0xff;
|
||||||
|
// stolen from some site, likely incorrect
|
||||||
|
int b = 1.164 * (y - 16) + 2.018 * (u - 128);
|
||||||
|
int g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128);
|
||||||
|
int r = 1.164 * (y - 16) + 1.596 * (v - 128);
|
||||||
|
#define CL(x) FFMAX(FFMIN((x), 255), 0)
|
||||||
|
palette[i] = (alpha << 24) | CL(r) | (CL(g) << 8) | (CL(b) << 16);
|
||||||
|
#undef CL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void crop_image(struct sub_bitmap *part)
|
||||||
|
{
|
||||||
|
if (part->w < 1 || part->h < 1)
|
||||||
|
return;
|
||||||
|
struct osd_bmp_indexed *bmp = part->bitmap;
|
||||||
|
bool invisible[256];
|
||||||
|
for (int n = 0; n < 256; n++)
|
||||||
|
invisible[n] = !(bmp->palette[n] >> 24);
|
||||||
|
int y0 = 0, y1 = part->h, x0 = part->w, x1 = 0;
|
||||||
|
bool y_all_invisible = true;
|
||||||
|
for (int y = 0; y < part->h; y++) {
|
||||||
|
uint8_t *pixels = bmp->bitmap + part->stride * y;
|
||||||
|
int cur = 0;
|
||||||
|
while (cur < part->w && invisible[pixels[cur]])
|
||||||
|
cur++;
|
||||||
|
int start_visible = cur;
|
||||||
|
int last_visible = -1;
|
||||||
|
while (cur < part->w) {
|
||||||
|
if (!invisible[pixels[cur]])
|
||||||
|
last_visible = cur;
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
x0 = FFMIN(x0, start_visible);
|
||||||
|
x1 = FFMAX(x1, last_visible);
|
||||||
|
bool all_invisible = last_visible == -1;
|
||||||
|
if (all_invisible) {
|
||||||
|
if (y_all_invisible)
|
||||||
|
y0 = y;
|
||||||
|
} else {
|
||||||
|
y_all_invisible = false;
|
||||||
|
y1 = y + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bmp->bitmap += x0 + y0 * part->stride;
|
||||||
|
part->w = FFMAX(x1 - x0, 0);
|
||||||
|
part->h = FFMAX(y1 - y0, 0);
|
||||||
|
part->x += x0;
|
||||||
|
part->y += y0;
|
||||||
|
}
|
||||||
|
|
||||||
static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
|
static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
|
||||||
{
|
{
|
||||||
unsigned int i, x, y;
|
unsigned int i, x, y;
|
||||||
|
@ -391,6 +455,18 @@ static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
|
||||||
dst += len;
|
dst += len;
|
||||||
}
|
}
|
||||||
apply_palette_crop(this, 0, 0, this->pal_width, this->pal_height);
|
apply_palette_crop(this, 0, 0, this->pal_width, this->pal_height);
|
||||||
|
|
||||||
|
struct sub_bitmap *sub_part = &this->sub_part;
|
||||||
|
struct osd_bmp_indexed *bmp = &this->borrowed_bmp;
|
||||||
|
bmp->bitmap = this->pal_image;
|
||||||
|
setup_palette(this, bmp->palette);
|
||||||
|
sub_part->bitmap = bmp;
|
||||||
|
sub_part->stride = this->pal_width;
|
||||||
|
sub_part->w = this->pal_width;
|
||||||
|
sub_part->h = this->pal_height;
|
||||||
|
sub_part->x = this->pal_start_col;
|
||||||
|
sub_part->y = this->pal_start_row;
|
||||||
|
crop_image(sub_part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -768,40 +844,18 @@ void spudec_get_indexed(void *this, struct mp_eosd_res *dim,
|
||||||
*res = (struct sub_bitmaps) { .format = SUBBITMAP_INDEXED };
|
*res = (struct sub_bitmaps) { .format = SUBBITMAP_INDEXED };
|
||||||
struct sub_bitmap *part = &spu->borrowed_sub_part;
|
struct sub_bitmap *part = &spu->borrowed_sub_part;
|
||||||
res->parts = part;
|
res->parts = part;
|
||||||
if (spudec_visible(spu)) {
|
*part = spu->sub_part;
|
||||||
struct osd_bmp_indexed *bmp = &spu->borrowed_bmp;
|
// Empty subs do happen when cropping
|
||||||
part->bitmap = bmp;
|
bool empty = part->w < 1 || part->h < 1;
|
||||||
bmp->bitmap = spu->pal_image;
|
if (spudec_visible(spu) && !empty) {
|
||||||
part->stride = spu->pal_width;
|
|
||||||
part->w = spu->pal_width;
|
|
||||||
part->h = spu->pal_height;
|
|
||||||
double xscale = (double) (dim->w - dim->ml - dim->mr) / spu->orig_frame_width;
|
double xscale = (double) (dim->w - dim->ml - dim->mr) / spu->orig_frame_width;
|
||||||
double yscale = (double) (dim->h - dim->mt - dim->mb) / spu->orig_frame_height;
|
double yscale = (double) (dim->h - dim->mt - dim->mb) / spu->orig_frame_height;
|
||||||
part->x = spu->pal_start_col * xscale + dim->ml;
|
part->x = part->x * xscale + dim->ml;
|
||||||
part->y = spu->pal_start_row * yscale + dim->mt;
|
part->y = part->y * yscale + dim->mt;
|
||||||
part->dw = part->w * xscale;
|
part->dw = part->w * xscale;
|
||||||
part->dh = part->h * yscale;
|
part->dh = part->h * yscale;
|
||||||
res->num_parts = 1;
|
res->num_parts = 1;
|
||||||
memset(bmp->palette, 0, sizeof(bmp->palette));
|
res->scaled = true;
|
||||||
for (int i = 0; i < 4; ++i) {
|
|
||||||
int alpha = spu->alpha[i];
|
|
||||||
// extend 4 -> 8 bit
|
|
||||||
alpha |= alpha << 4;
|
|
||||||
if (spu->custom && (spu->cuspal[i] >> 31) != 0)
|
|
||||||
alpha = 0;
|
|
||||||
int color = spu->custom ? spu->cuspal[i] :
|
|
||||||
spu->global_palette[spu->palette[i]];
|
|
||||||
int y = (color >> 16) & 0xff;
|
|
||||||
int u = (color >> 8) & 0xff;
|
|
||||||
int v = color & 0xff;
|
|
||||||
// stolen from some site, likely incorrect
|
|
||||||
int b = 1.164 * (y - 16) + 2.018 * (u - 128);
|
|
||||||
int g = 1.164 * (y - 16) - 0.813 * (v - 128) - 0.391 * (u - 128);
|
|
||||||
int r = 1.164 * (y - 16) + 1.596 * (v - 128);
|
|
||||||
#define CL(x) FFMAX(FFMIN((x), 255), 0)
|
|
||||||
bmp->palette[i] = (alpha << 24) | CL(r) | (CL(g) << 8) | (CL(b) << 16);
|
|
||||||
#undef CL
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue