diff options
Diffstat (limited to 'sub')
-rw-r--r-- | sub/ass_mp.h | 8 | ||||
-rw-r--r-- | sub/img_convert.c | 144 | ||||
-rw-r--r-- | sub/img_convert.h | 6 | ||||
-rw-r--r-- | sub/osd.c | 10 | ||||
-rw-r--r-- | sub/osd.h | 33 | ||||
-rw-r--r-- | sub/osd_dummy.c | 3 | ||||
-rw-r--r-- | sub/osd_libass.c | 9 | ||||
-rw-r--r-- | sub/sd_ass.c | 11 | ||||
-rw-r--r-- | sub/sd_lavc.c | 219 |
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); @@ -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); @@ -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 = ¤t->inbitmaps[current->count]; - struct osd_bmp_indexed *img = ¤t->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); } |