summaryrefslogtreecommitdiffstats
path: root/sub
diff options
context:
space:
mode:
Diffstat (limited to 'sub')
-rw-r--r--sub/ass_mp.h8
-rw-r--r--sub/img_convert.c144
-rw-r--r--sub/img_convert.h6
-rw-r--r--sub/osd.c10
-rw-r--r--sub/osd.h33
-rw-r--r--sub/osd_dummy.c3
-rw-r--r--sub/osd_libass.c9
-rw-r--r--sub/sd_ass.c11
-rw-r--r--sub/sd_lavc.c219
9 files changed, 220 insertions, 223 deletions
diff --git a/sub/ass_mp.h b/sub/ass_mp.h
index b4cae24ddc..20f0ebe9bd 100644
--- a/sub/ass_mp.h
+++ b/sub/ass_mp.h
@@ -23,7 +23,8 @@
#include <stdint.h>
#include <stdbool.h>
-#include "config.h"
+#include <ass/ass.h>
+#include <ass/ass_types.h>
// This is probably arbitrary.
// sd_lavc_conv might indirectly still assume this PlayResY, though.
@@ -35,10 +36,6 @@
// m_color argument
#define MP_ASS_COLOR(c) MP_ASS_RGBA((c).r, (c).g, (c).b, (c).a)
-#if HAVE_LIBASS
-#include <ass/ass.h>
-#include <ass/ass_types.h>
-
struct MPOpts;
struct mpv_global;
struct mp_osd_res;
@@ -57,5 +54,4 @@ struct sub_bitmaps;
void mp_ass_render_frame(ASS_Renderer *renderer, ASS_Track *track, double time,
struct sub_bitmaps *res);
-#endif /* HAVE_LIBASS */
#endif /* MPLAYER_ASS_MP_H */
diff --git a/sub/img_convert.c b/sub/img_convert.c
index d86b8f4ad1..78be881fdf 100644
--- a/sub/img_convert.c
+++ b/sub/img_convert.c
@@ -41,106 +41,21 @@ struct osd_conv_cache *osd_conv_cache_new(void)
return talloc_zero(NULL, struct osd_conv_cache);
}
-static void rgba_to_premultiplied_rgba(uint32_t *colors, size_t count)
+void mp_blur_rgba_sub_bitmap(struct sub_bitmap *d, double gblur)
{
- for (int n = 0; n < count; n++) {
- uint32_t c = colors[n];
- unsigned b = c & 0xFF;
- unsigned g = (c >> 8) & 0xFF;
- unsigned r = (c >> 16) & 0xFF;
- unsigned a = (c >> 24) & 0xFF;
- b = b * a / 255;
- g = g * a / 255;
- r = r * a / 255;
- colors[n] = b | (g << 8) | (r << 16) | (a << 24);
- }
-}
-
-bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
-{
- struct sub_bitmaps src = *imgs;
- if (src.format != SUBBITMAP_INDEXED)
- return false;
-
- imgs->format = SUBBITMAP_RGBA;
- talloc_free(c->parts);
- imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
-
- for (int n = 0; n < src.num_parts; n++) {
- struct sub_bitmap *d = &imgs->parts[n];
- struct sub_bitmap *s = &src.parts[n];
- struct osd_bmp_indexed sb = *(struct osd_bmp_indexed *)s->bitmap;
-
- rgba_to_premultiplied_rgba(sb.palette, 256);
-
- *d = *s;
- struct mp_image *image = mp_image_alloc(IMGFMT_BGRA, s->w, s->h);
- talloc_steal(c->parts, image);
- if (!image) {
- // on OOM, skip the region by making it 0 sized
- d->w = d->h = d->dw = d->dh = 0;
- continue;
- }
-
- d->stride = image->stride[0];
- d->bitmap = image->planes[0];
-
- for (int y = 0; y < s->h; y++) {
- uint8_t *inbmp = sb.bitmap + y * s->stride;
- uint32_t *outbmp = (uint32_t*)((uint8_t*)d->bitmap + y * d->stride);
- for (int x = 0; x < s->w; x++)
- *outbmp++ = sb.palette[*inbmp++];
- }
- }
- return true;
-}
-
-bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
- double gblur)
-{
- struct sub_bitmaps src = *imgs;
- if (src.format != SUBBITMAP_RGBA)
- return false;
-
- talloc_free(c->parts);
- imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
-
- for (int n = 0; n < src.num_parts; n++) {
- struct sub_bitmap *d = &imgs->parts[n];
- struct sub_bitmap *s = &src.parts[n];
+ struct mp_image *tmp1 = mp_image_alloc(IMGFMT_BGRA, d->w, d->h);
+ if (tmp1) { // on OOM, skip region
+ struct mp_image s = {0};
+ mp_image_setfmt(&s, IMGFMT_BGRA);
+ mp_image_set_size(&s, d->w, d->h);
+ s.stride[0] = d->stride;
+ s.planes[0] = d->bitmap;
- // add a transparent padding border to reduce artifacts
- int pad = 5;
- struct mp_image *temp = mp_image_alloc(IMGFMT_BGRA, s->w + pad * 2,
- s->h + pad * 2);
- if (!temp)
- continue; // on OOM, skip region
- memset_pic(temp->planes[0], 0, temp->w * 4, temp->h, temp->stride[0]);
- uint8_t *p0 = temp->planes[0] + pad * 4 + pad * temp->stride[0];
- memcpy_pic(p0, s->bitmap, s->w * 4, s->h, temp->stride[0], s->stride);
-
- double sx = (double)s->dw / s->w;
- double sy = (double)s->dh / s->h;
-
- d->x = s->x - pad * sx;
- d->y = s->y - pad * sy;
- d->w = d->dw = s->dw + pad * 2 * sx;
- d->h = d->dh = s->dh + pad * 2 * sy;
- struct mp_image *image = mp_image_alloc(IMGFMT_BGRA, d->w, d->h);
- talloc_steal(c->parts, image);
- if (image) {
- d->stride = image->stride[0];
- d->bitmap = image->planes[0];
+ mp_image_copy(tmp1, &s);
- mp_image_sw_blur_scale(image, temp, gblur);
- } else {
- // on OOM, skip region
- *d = *s;
- }
-
- talloc_free(temp);
+ mp_image_sw_blur_scale(&s, tmp1, gblur);
}
- return true;
+ talloc_free(tmp1);
}
// If RGBA parts need scaling, scale them.
@@ -161,6 +76,7 @@ bool osd_scale_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
talloc_free(c->parts);
imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
+ imgs->packed = NULL;
// Note: we scale all parts, since most likely all need scaling anyway, and
// to get a proper copy of all data in the imgs list.
@@ -193,41 +109,6 @@ bool osd_scale_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
return true;
}
-static void rgba_to_gray(uint32_t *colors, size_t count)
-{
- for (int n = 0; n < count; n++) {
- uint32_t c = colors[n];
- int b = c & 0xFF;
- int g = (c >> 8) & 0xFF;
- int r = (c >> 16) & 0xFF;
- int a = (c >> 24) & 0xFF;
- r = g = b = (r + g + b) / 3;
- colors[n] = b | (g << 8) | (r << 16) | (a << 24);
- }
-}
-
-bool osd_conv_idx_to_gray(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
-{
- struct sub_bitmaps src = *imgs;
- if (src.format != SUBBITMAP_INDEXED)
- return false;
-
- talloc_free(c->parts);
- imgs->parts = c->parts = talloc_array(c, struct sub_bitmap, src.num_parts);
-
- for (int n = 0; n < src.num_parts; n++) {
- struct sub_bitmap *d = &imgs->parts[n];
- struct sub_bitmap *s = &src.parts[n];
- struct osd_bmp_indexed sb = *(struct osd_bmp_indexed *)s->bitmap;
-
- rgba_to_gray(sb.palette, 256);
-
- *d = *s;
- d->bitmap = talloc_memdup(c->parts, &sb, sizeof(sb));
- }
- return true;
-}
-
static void draw_ass_rgba(unsigned char *src, int src_w, int src_h,
int src_stride, unsigned char *dst, size_t dst_stride,
int dst_x, int dst_y, uint32_t color)
@@ -274,6 +155,7 @@ bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs)
imgs->format = SUBBITMAP_RGBA;
imgs->parts = c->part;
imgs->num_parts = num_bb;
+ imgs->packed = NULL;
size_t newsize = 0;
for (int n = 0; n < num_bb; n++) {
diff --git a/sub/img_convert.h b/sub/img_convert.h
index 85ba5bb828..a0020df497 100644
--- a/sub/img_convert.h
+++ b/sub/img_convert.h
@@ -5,19 +5,17 @@
struct osd_conv_cache;
struct sub_bitmaps;
+struct sub_bitmap;
struct mp_rect;
struct osd_conv_cache *osd_conv_cache_new(void);
// These functions convert from one OSD format to another. On success, they copy
// the converted image data into c, and change imgs to point to the data.
-bool osd_conv_idx_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
bool osd_conv_ass_to_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
// Sub postprocessing
-bool osd_conv_blur_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs,
- double gblur);
+void mp_blur_rgba_sub_bitmap(struct sub_bitmap *d, double gblur);
bool osd_scale_rgba(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
-bool osd_conv_idx_to_gray(struct osd_conv_cache *c, struct sub_bitmaps *imgs);
bool mp_sub_bitmaps_bb(struct sub_bitmaps *imgs, struct mp_rect *out_bb);
diff --git a/sub/osd.c b/sub/osd.c
index 4e269ce5aa..a0618aafd9 100644
--- a/sub/osd.c
+++ b/sub/osd.c
@@ -295,16 +295,6 @@ static void render_object(struct osd_state *osd, struct osd_object *obj,
bool cached = false; // do we have a copy of all the image data?
- if (out_imgs->format == SUBBITMAP_INDEXED && opts->sub_gray)
- cached |= osd_conv_idx_to_gray(obj->cache[0], out_imgs);
-
- if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_INDEXED)
- cached |= osd_conv_idx_to_rgba(obj->cache[1], out_imgs);
-
- if (out_imgs->format == SUBBITMAP_RGBA && opts->sub_gauss != 0.0f)
- cached |= osd_conv_blur_rgba(obj->cache[2], out_imgs, opts->sub_gauss);
-
- // Do this conversion last to not trigger gauss blurring for ASS
if (formats[SUBBITMAP_RGBA] && out_imgs->format == SUBBITMAP_LIBASS)
cached |= osd_conv_ass_to_rgba(obj->cache[3], out_imgs);
diff --git a/sub/osd.h b/sub/osd.h
index 550b31e5a7..7cfc695873 100644
--- a/sub/osd.h
+++ b/sub/osd.h
@@ -29,19 +29,10 @@ enum sub_bitmap_format {
SUBBITMAP_EMPTY = 0,// no bitmaps; always has num_parts==0
SUBBITMAP_LIBASS, // A8, with a per-surface blend color (libass.color)
SUBBITMAP_RGBA, // B8G8R8A8 (MSB=A, LSB=B), scaled, premultiplied alpha
- SUBBITMAP_INDEXED, // scaled, bitmap points to osd_bmp_indexed
SUBBITMAP_COUNT
};
-// For SUBBITMAP_INDEXED
-struct osd_bmp_indexed {
- uint8_t *bitmap;
- // Each entry is like a pixel in SUBBITMAP_RGBA format, but using straight
- // alpha.
- uint32_t palette[256];
-};
-
struct sub_bitmap {
void *bitmap;
int stride;
@@ -51,6 +42,11 @@ struct sub_bitmap {
int x, y;
int dw, dh;
+ // If the containing struct sub_bitmaps has the packed field set, then this
+ // is the position within the source. (Strictly speaking this is redundant
+ // with the bitmap pointer.)
+ int src_x, src_y;
+
struct {
uint32_t color;
} libass;
@@ -69,6 +65,17 @@ struct sub_bitmaps {
struct sub_bitmap *parts;
int num_parts;
+ // Packed representation of the bitmap data. If non-NULL, then the
+ // parts[].bitmap pointer points into the image data here (and stride will
+ // correspond to packed->stride[0]).
+ // SUBBITMAP_RGBA: IMGFMT_BGRA (exact match)
+ // Other formats have this set to NULL.
+ struct mp_image *packed;
+
+ // Bounding box for the packed image. All parts will be within the bounding
+ // box. (The origin of the box is at (0,0).)
+ int packed_w, packed_h;
+
int change_id; // Incremented on each change
};
@@ -107,6 +114,12 @@ enum mp_osd_font_codepoints {
OSD_PB_1 = 0x13,
};
+
+// Never valid UTF-8, so we expect it's free for use.
+// Specially interpreted by osd_libass.c, in order to allow/escape ASS tags.
+#define OSD_ASS_0 "\xFD"
+#define OSD_ASS_1 "\xFE"
+
struct osd_style_opts {
char *font;
float font_size;
@@ -200,7 +213,5 @@ void osd_set_external(struct osd_state *osd, void *id, int res_x, int res_y,
// doesn't need locking
void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function);
-extern const char *const osd_ass_0;
-extern const char *const osd_ass_1;
#endif /* MPLAYER_SUB_H */
diff --git a/sub/osd_dummy.c b/sub/osd_dummy.c
index 5c3cc76200..d9c366e1ac 100644
--- a/sub/osd_dummy.c
+++ b/sub/osd_dummy.c
@@ -6,9 +6,6 @@
#include "mpv_talloc.h"
#include "osd.h"
-const char *const osd_ass_0 = "";
-const char *const osd_ass_1 = "";
-
void osd_init_backend(struct osd_state *osd)
{
}
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index 30d404d8c6..6a2efa6603 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -179,13 +179,10 @@ static void clear_ass(struct ass_state *ass)
void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function)
{
// 0xFF is never valid UTF-8, so we can use it to escape OSD symbols.
+ // (Same trick as OSD_ASS_0/OSD_ASS_1.)
snprintf(buffer, buffer_size, "\xFF%c", osd_function);
}
-// Same trick as above: never valid UTF-8, so we expect it's free for use.
-const char *const osd_ass_0 = "\xFD";
-const char *const osd_ass_1 = "\xFE";
-
static void mangle_ass(bstr *dst, const char *in)
{
bool escape_ass = true;
@@ -198,8 +195,8 @@ static void mangle_ass(bstr *dst, const char *in)
in += 2;
continue;
}
- if (*in == '\xFD' || *in == '\xFE') {
- escape_ass = *in == '\xFE';
+ if (*in == OSD_ASS_0[0] || *in == OSD_ASS_1[0]) {
+ escape_ass = *in == OSD_ASS_1[0];
in += 1;
continue;
}
diff --git a/sub/sd_ass.c b/sub/sd_ass.c
index 788b78f3a4..6f35053370 100644
--- a/sub/sd_ass.c
+++ b/sub/sd_ass.c
@@ -117,11 +117,11 @@ static void add_subtitle_fonts(struct sd *sd)
{
struct sd_ass_priv *ctx = sd->priv;
struct MPOpts *opts = sd->opts;
- if (!opts->ass_enabled || !sd->attachments)
+ if (!opts->ass_enabled || !opts->use_embedded_fonts || !sd->attachments)
return;
for (int i = 0; i < sd->attachments->num_entries; i++) {
struct demux_attachment *f = &sd->attachments->entries[i];
- if (opts->use_embedded_fonts && attachment_is_font(sd->log, f))
+ if (attachment_is_font(sd->log, f))
ass_add_font(ctx->ass_library, f->name, f->data, f->data_size);
}
}
@@ -270,8 +270,8 @@ static void decode(struct sd *sd, struct demux_packet *packet)
// Note that for this packet format, libass has an internal mechanism
// for discarding duplicate (already seen) packets.
ass_process_chunk(track, packet->buffer, packet->len,
- lrint(packet->pts * 1000),
- lrint(packet->duration * 1000));
+ llrint(packet->pts * 1000),
+ llrint(packet->duration * 1000));
}
}
@@ -422,7 +422,8 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, double pts,
{
struct sd_ass_priv *ctx = sd->priv;
struct MPOpts *opts = sd->opts;
- bool no_ass = !opts->ass_enabled || ctx->on_top;
+ bool no_ass = !opts->ass_enabled || ctx->on_top ||
+ opts->ass_style_override == 5;
bool converted = ctx->is_converted || no_ass;
ASS_Track *track = no_ass ? ctx->shadow_track : ctx->ass_track;
ASS_Renderer *renderer = ctx->ass_renderer;
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index 56377b213e..7f68a2224e 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -31,6 +31,8 @@
#include "demux/stheader.h"
#include "options/options.h"
#include "video/mp_image.h"
+#include "video/out/bitmap_packer.h"
+#include "img_convert.h"
#include "sd.h"
#include "dec_sub.h"
@@ -39,9 +41,11 @@
struct sub {
bool valid;
AVSubtitle avsub;
- int count;
struct sub_bitmap *inbitmaps;
- struct osd_bmp_indexed *imgs;
+ int count;
+ struct mp_image *data;
+ int bound_w, bound_h;
+ int src_w, src_h;
double pts;
double endpts;
int64_t id;
@@ -63,6 +67,7 @@ struct sd_lavc_priv {
double current_pts;
struct seekpoint *seekpoints;
int num_seekpoints;
+ struct bitmap_packer *packer;
};
static void get_resolution(struct sd *sd, int wh[2])
@@ -118,6 +123,7 @@ static int init(struct sd *sd)
if (!ctx)
goto error;
mp_lavc_set_extradata(ctx, sd->codec->extradata, sd->codec->extradata_size);
+#if LIBAVCODEC_VERSION_MICRO >= 100
if (cid == AV_CODEC_ID_HDMV_PGS_SUBTITLE) {
// We don't always want to set this, because the ridiculously shitty
// libavcodec API will mess with certain fields (end_display_time)
@@ -129,17 +135,21 @@ static int init(struct sd *sd)
// which coincidentally won't be overridden by the ridiculously shitty
// pkt_timebase code. also, Libav doesn't have the pkt_timebase field,
// because Libav tends to avoid _adding_ ridiculously shitty APIs.
-#if LIBAVCODEC_VERSION_MICRO >= 100
priv->pkt_timebase = (AVRational){1, AV_TIME_BASE};
ctx->pkt_timebase = priv->pkt_timebase;
-#endif
+ } else {
+ // But old ffmpeg releases have a buggy pkt_timebase check, because the
+ // shit above wasn't bad enough!
+ ctx->pkt_timebase = (AVRational){0, 0};
}
+#endif
if (avcodec_open2(ctx, sub_codec, NULL) < 0)
goto error;
priv->avctx = ctx;
sd->priv = priv;
priv->displayed_id = -1;
priv->current_pts = MP_NOPTS_VALUE;
+ priv->packer = talloc_zero(priv, struct bitmap_packer);
return 0;
error:
@@ -169,9 +179,159 @@ static void alloc_sub(struct sd_lavc_priv *priv)
// clear only some fields; the memory allocs can be reused
priv->subs[0].valid = false;
priv->subs[0].count = 0;
+ priv->subs[0].src_w = 0;
+ priv->subs[0].src_h = 0;
priv->subs[0].id = priv->new_id++;
}
+static void convert_pal(uint32_t *colors, size_t count, bool gray)
+{
+ for (int n = 0; n < count; n++) {
+ uint32_t c = colors[n];
+ int b = c & 0xFF;
+ int g = (c >> 8) & 0xFF;
+ int r = (c >> 16) & 0xFF;
+ int a = (c >> 24) & 0xFF;
+ if (gray)
+ r = g = b = (r + g + b) / 3;
+ // from straight to pre-multiplied alpha
+ b = b * a / 255;
+ g = g * a / 255;
+ r = r * a / 255;
+ colors[n] = b | (g << 8) | (r << 16) | (a << 24);
+ }
+}
+
+// Initialize sub from sub->avsub.
+static void read_sub_bitmaps(struct sd *sd, struct sub *sub)
+{
+ struct MPOpts *opts = sd->opts;
+ struct sd_lavc_priv *priv = sd->priv;
+ AVSubtitle *avsub = &sub->avsub;
+
+ MP_TARRAY_GROW(priv, sub->inbitmaps, avsub->num_rects);
+
+ packer_set_size(priv->packer, avsub->num_rects);
+
+ // If we blur, we want a transparent region around the bitmap data to
+ // avoid "cut off" artifacts on the borders.
+ bool apply_blur = opts->sub_gauss != 0.0f;
+ int extend = apply_blur ? 5 : 0;
+ // Assume consumers may use bilinear scaling on it (2x2 filter)
+ int padding = 1 + extend;
+
+ priv->packer->padding = padding;
+
+ // For the sake of libswscale, which in some cases takes sub-rects as
+ // source images, and wants 16 byte start pointer and stride alignment.
+ int align = 4;
+
+ for (int i = 0; i < avsub->num_rects; i++) {
+ struct AVSubtitleRect *r = avsub->rects[i];
+ struct sub_bitmap *b = &sub->inbitmaps[sub->count];
+
+ if (r->type != SUBTITLE_BITMAP) {
+ MP_ERR(sd, "unsupported subtitle type from libavcodec\n");
+ continue;
+ }
+ if (!(r->flags & AV_SUBTITLE_FLAG_FORCED) && opts->forced_subs_only)
+ continue;
+ if (r->w <= 0 || r->h <= 0)
+ continue;
+
+ b->bitmap = r; // save for later (dumb hack to avoid more complexity)
+
+ priv->packer->in[sub->count] = (struct pos){r->w + (align - 1), r->h};
+ sub->count++;
+ }
+
+ priv->packer->count = sub->count;
+
+ if (packer_pack(priv->packer) < 0) {
+ MP_ERR(sd, "Unable to pack subtitle bitmaps.\n");
+ sub->count = 0;
+ }
+
+ if (!sub->count)
+ return;
+
+ struct pos bb[2];
+ packer_get_bb(priv->packer, bb);
+
+ sub->bound_w = bb[1].x;
+ sub->bound_h = bb[1].y;
+
+ if (!sub->data || sub->data->w < sub->bound_w || sub->data->h < sub->bound_h) {
+ talloc_free(sub->data);
+ sub->data = mp_image_alloc(IMGFMT_BGRA, priv->packer->w, priv->packer->h);
+ if (!sub->data) {
+ sub->count = 0;
+ return;
+ }
+ talloc_steal(priv, sub->data);
+ }
+
+ for (int i = 0; i < sub->count; i++) {
+ struct sub_bitmap *b = &sub->inbitmaps[i];
+ struct pos pos = priv->packer->result[i];
+ struct AVSubtitleRect *r = b->bitmap;
+#if HAVE_AV_SUBTITLE_NOPICT
+ uint8_t **data = r->data;
+ int *linesize = r->linesize;
+#else
+ uint8_t **data = r->pict.data;
+ int *linesize = r->pict.linesize;
+#endif
+ b->w = r->w;
+ b->h = r->h;
+ b->x = r->x;
+ b->y = r->y;
+
+ // Choose such that the extended start position is aligned.
+ pos.x = MP_ALIGN_UP(pos.x - extend, align) + extend;
+
+ b->src_x = pos.x;
+ b->src_y = pos.y;
+ b->stride = sub->data->stride[0];
+ b->bitmap = sub->data->planes[0] + pos.y * b->stride + pos.x * 4;
+
+ sub->src_w = FFMAX(sub->src_w, b->x + b->w);
+ sub->src_h = FFMAX(sub->src_h, b->y + b->h);
+
+ assert(r->nb_colors > 0);
+ assert(r->nb_colors <= 256);
+ uint32_t pal[256] = {0};
+ memcpy(pal, data[1], r->nb_colors * 4);
+ convert_pal(pal, 256, opts->sub_gray);
+
+ for (int y = -padding; y < b->h + padding; y++) {
+ uint32_t *out = (uint32_t*)((char*)b->bitmap + y * b->stride);
+ int start = 0;
+ for (int x = -padding; x < 0; x++)
+ out[x] = 0;
+ if (y >= 0 && y < b->h) {
+ uint8_t *in = data[0] + y * linesize[0];
+ for (int x = 0; x < b->w; x++)
+ *out++ = pal[*in++];
+ start = b->w;
+ }
+ for (int x = start; x < b->w + padding; x++)
+ *out++ = 0;
+ }
+
+ b->bitmap = (char*)b->bitmap - extend * b->stride - extend * 4;
+ b->src_x -= extend;
+ b->src_y -= extend;
+ b->x -= extend;
+ b->y -= extend;
+ b->w += extend * 2;
+ b->h += extend * 2;
+
+ if (apply_blur)
+ mp_blur_rgba_sub_bitmap(b, opts->sub_gauss);
+ }
+}
+
static void decode(struct sd *sd, struct demux_packet *packet)
{
struct MPOpts *opts = sd->opts;
@@ -246,40 +406,7 @@ static void decode(struct sd *sd, struct demux_packet *packet)
current->endpts = endpts;
current->avsub = sub;
- MP_TARRAY_GROW(priv, current->inbitmaps, sub.num_rects);
- MP_TARRAY_GROW(priv, current->imgs, sub.num_rects);
-
- for (int i = 0; i < sub.num_rects; i++) {
- struct AVSubtitleRect *r = sub.rects[i];
- struct sub_bitmap *b = &current->inbitmaps[current->count];
- struct osd_bmp_indexed *img = &current->imgs[current->count];
- if (r->type != SUBTITLE_BITMAP) {
- MP_ERR(sd, "unsupported subtitle type from libavcodec\n");
- continue;
- }
- if (!(r->flags & AV_SUBTITLE_FLAG_FORCED) && opts->forced_subs_only)
- continue;
- if (r->w <= 0 || r->h <= 0)
- continue;
-#if HAVE_AV_SUBTITLE_NOPICT
- uint8_t **data = r->data;
- int *linesize = r->linesize;
-#else
- uint8_t **data = r->pict.data;
- int *linesize = r->pict.linesize;
-#endif
- img->bitmap = data[0];
- assert(r->nb_colors > 0);
- assert(r->nb_colors * 4 <= sizeof(img->palette));
- memcpy(img->palette, data[1], r->nb_colors * 4);
- b->bitmap = img;
- b->stride = linesize[0];
- b->w = r->w;
- b->h = r->h;
- b->x = r->x;
- b->y = r->y;
- current->count++;
- }
+ read_sub_bitmaps(sd, current);
if (pts != MP_NOPTS_VALUE) {
for (int n = 0; n < priv->num_seekpoints; n++) {
@@ -331,7 +458,10 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
if (priv->displayed_id != current->id)
res->change_id++;
priv->displayed_id = current->id;
- res->format = SUBBITMAP_INDEXED;
+ res->packed = current->data;
+ res->packed_w = current->bound_w;
+ res->packed_h = current->bound_h;
+ res->format = SUBBITMAP_RGBA;
double video_par = 0;
if (priv->avctx->codec_id == AV_CODEC_ID_DVD_SUBTITLE &&
@@ -348,14 +478,9 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, double pts,
d.ml = d.mr = d.mt = d.mb = 0;
int insize[2];
get_resolution(sd, insize);
- for (int n = 0; n < res->num_parts; n++) {
- struct sub_bitmap *p = &res->parts[n];
- if ((p->x + p->w > insize[0] || p->y + p->h > insize[1]) &&
- priv->video_params.w > insize[0] && priv->video_params.h > insize[1])
- {
- insize[0] = priv->video_params.w;
- insize[1] = priv->video_params.h;
- }
+ if (current->src_w > insize[0] || current->src_h > insize[1]) {
+ insize[0] = priv->video_params.w;
+ insize[1] = priv->video_params.h;
}
osd_rescale_bitmaps(res, insize[0], insize[1], d, video_par);
}