summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sub/spudec.c114
1 files changed, 84 insertions, 30 deletions
diff --git a/sub/spudec.c b/sub/spudec.c
index 8ee22a5267..e9084dcb32 100644
--- a/sub/spudec.c
+++ b/sub/spudec.c
@@ -125,8 +125,8 @@ typedef struct {
struct palette_crop_cache palette_crop_cache;
- struct sub_bitmap borrowed_sub_part;
struct old_osd_planar borrowed_sub_image;
+ struct sub_bitmap sub_part, borrowed_sub_part;
struct osd_bmp_indexed borrowed_bmp;
} spudec_handle_t;
@@ -344,6 +344,70 @@ int spudec_apply_palette_crop(void *this, uint32_t palette,
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)
{
unsigned int i, x, y;
@@ -391,6 +455,18 @@ static void spudec_process_data(spudec_handle_t *this, packet_t *packet)
dst += len;
}
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 };
struct sub_bitmap *part = &spu->borrowed_sub_part;
res->parts = part;
- if (spudec_visible(spu)) {
- struct osd_bmp_indexed *bmp = &spu->borrowed_bmp;
- part->bitmap = bmp;
- bmp->bitmap = spu->pal_image;
- part->stride = spu->pal_width;
- part->w = spu->pal_width;
- part->h = spu->pal_height;
+ *part = spu->sub_part;
+ // Empty subs do happen when cropping
+ bool empty = part->w < 1 || part->h < 1;
+ if (spudec_visible(spu) && !empty) {
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;
- part->x = spu->pal_start_col * xscale + dim->ml;
- part->y = spu->pal_start_row * yscale + dim->mt;
+ part->x = part->x * xscale + dim->ml;
+ part->y = part->y * yscale + dim->mt;
part->dw = part->w * xscale;
part->dh = part->h * yscale;
res->num_parts = 1;
- memset(bmp->palette, 0, sizeof(bmp->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)
- bmp->palette[i] = (alpha << 24) | CL(r) | (CL(g) << 8) | (CL(b) << 16);
-#undef CL
- }
+ res->scaled = true;
}
}