diff --git a/meson.build b/meson.build index d4c75a907f..a55e550cb3 100644 --- a/meson.build +++ b/meson.build @@ -203,6 +203,7 @@ sources = files( 'sub/lavc_conv.c', 'sub/osd.c', 'sub/osd_libass.c', + 'sub/packer.c', 'sub/sd_ass.c', 'sub/sd_lavc.c', diff --git a/sub/ass_mp.c b/sub/ass_mp.c index c8b1bd05d6..7e81bb266d 100644 --- a/sub/ass_mp.c +++ b/sub/ass_mp.c @@ -17,7 +17,6 @@ * License along with mpv. If not, see . */ -#include #include #include #include @@ -32,12 +31,8 @@ #include "common/msg.h" #include "options/path.h" #include "ass_mp.h" -#include "img_convert.h" #include "osd.h" #include "stream/stream.h" -#include "options/options.h" -#include "video/out/bitmap_packer.h" -#include "video/mp_image.h" // res_y should be track->PlayResY // It determines scaling of font sizes and more. @@ -159,294 +154,6 @@ void mp_ass_flush_old_events(ASS_Track *track, long long ts) } } -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) -{ - const unsigned int r = (color >> 24) & 0xff; - const unsigned int g = (color >> 16) & 0xff; - const unsigned int b = (color >> 8) & 0xff; - const unsigned int a = 0xff - (color & 0xff); - - dst += dst_y * dst_stride + dst_x * 4; - - for (int y = 0; y < src_h; y++, dst += dst_stride, src += src_stride) { - uint32_t *dstrow = (uint32_t *) dst; - for (int x = 0; x < src_w; x++) { - const unsigned int v = src[x]; - int rr = (r * a * v); - int gg = (g * a * v); - int bb = (b * a * v); - int aa = a * v; - uint32_t dstpix = dstrow[x]; - unsigned int dstb = dstpix & 0xFF; - unsigned int dstg = (dstpix >> 8) & 0xFF; - unsigned int dstr = (dstpix >> 16) & 0xFF; - unsigned int dsta = (dstpix >> 24) & 0xFF; - dstb = (bb + dstb * (255 * 255 - aa)) / (255 * 255); - dstg = (gg + dstg * (255 * 255 - aa)) / (255 * 255); - dstr = (rr + dstr * (255 * 255 - aa)) / (255 * 255); - dsta = (aa * 255 + dsta * (255 * 255 - aa)) / (255 * 255); - dstrow[x] = dstb | (dstg << 8) | (dstr << 16) | (dsta << 24); - } - } -} - -struct mp_ass_packer { - struct sub_bitmap *cached_parts; // only for the array memory - struct mp_image *cached_img; - struct sub_bitmaps cached_subs; - bool cached_subs_valid; - struct sub_bitmap rgba_imgs[MP_SUB_BB_LIST_MAX]; - struct bitmap_packer *packer; -}; - -// Free with talloc_free(). -struct mp_ass_packer *mp_ass_packer_alloc(void *ta_parent) -{ - struct mp_ass_packer *p = talloc_zero(ta_parent, struct mp_ass_packer); - p->packer = talloc_zero(p, struct bitmap_packer); - p->packer->padding = 1; // assume bilinear sampling - return p; -} - -static bool pack(struct mp_ass_packer *p, struct sub_bitmaps *res, int imgfmt) -{ - packer_set_size(p->packer, res->num_parts); - - for (int n = 0; n < res->num_parts; n++) - p->packer->in[n] = (struct pos){res->parts[n].w, res->parts[n].h}; - - if (p->packer->count == 0 || packer_pack(p->packer) < 0) - return false; - - struct pos bb[2]; - packer_get_bb(p->packer, bb); - - res->packed_w = bb[1].x; - res->packed_h = bb[1].y; - - if (!p->cached_img || p->cached_img->w < res->packed_w || - p->cached_img->h < res->packed_h || - p->cached_img->imgfmt != imgfmt) - { - talloc_free(p->cached_img); - p->cached_img = mp_image_alloc(imgfmt, p->packer->w, p->packer->h); - if (!p->cached_img) { - packer_reset(p->packer); - return false; - } - talloc_steal(p, p->cached_img); - } - - if (!mp_image_make_writeable(p->cached_img)) { - packer_reset(p->packer); - return false; - } - - res->packed = p->cached_img; - - for (int n = 0; n < res->num_parts; n++) { - struct sub_bitmap *b = &res->parts[n]; - struct pos pos = p->packer->result[n]; - - b->src_x = pos.x; - b->src_y = pos.y; - } - - return true; -} - -static void fill_padding_1(uint8_t *base, int w, int h, int stride, int padding) -{ - for (int row = 0; row < h; ++row) { - uint8_t *row_ptr = base + row * stride; - uint8_t left_pixel = row_ptr[0]; - uint8_t right_pixel = row_ptr[w - 1]; - - for (int i = 1; i <= padding; ++i) - row_ptr[-i] = left_pixel; - - for (int i = 0; i < padding; ++i) - row_ptr[w + i] = right_pixel; - } - - int row_bytes = (w + 2 * padding); - uint8_t *top_row = base - padding; - for (int i = 1; i <= padding; ++i) - memcpy(base - i * stride - padding, top_row, row_bytes); - - uint8_t *last_row = base + (h - 1) * stride - padding; - for (int i = 0; i < padding; ++i) - memcpy(base + (h + i) * stride - padding, last_row, row_bytes); -} - -static void fill_padding_4(uint8_t *base, int w, int h, int stride, int padding) -{ - for (int row = 0; row < h; ++row) { - uint32_t *row_ptr = (uint32_t *)(base + row * stride); - uint32_t left_pixel = row_ptr[0]; - uint32_t right_pixel = row_ptr[w - 1]; - - for (int i = 1; i <= padding; ++i) - row_ptr[-i] = left_pixel; - - for (int i = 0; i < padding; ++i) - row_ptr[w + i] = right_pixel; - } - - int row_bytes = (w + 2 * padding) * 4; - uint8_t *top_row = base - padding * 4; - for (int i = 1; i <= padding; ++i) - memcpy(base - i * stride - padding * 4, top_row, row_bytes); - - uint8_t *last_row = base + (h - 1) * stride - padding * 4; - for (int i = 0; i < padding; ++i) - memcpy(base + (h + i) * stride - padding * 4, last_row, row_bytes); -} - -static bool pack_libass(struct mp_ass_packer *p, struct sub_bitmaps *res) -{ - if (!pack(p, res, IMGFMT_Y8)) - return false; - - int padding = p->packer->padding; - uint8_t *base = res->packed->planes[0]; - int stride = res->packed->stride[0]; - - for (int n = 0; n < res->num_parts; n++) { - struct sub_bitmap *b = &res->parts[n]; - void *pdata = base + b->src_y * stride + b->src_x; - memcpy_pic(pdata, b->bitmap, b->w, b->h, stride, b->stride); - fill_padding_1(pdata, b->w, b->h, stride, padding); - - b->bitmap = pdata; - b->stride = stride; - } - - return true; -} - -static bool pack_rgba(struct mp_ass_packer *p, struct sub_bitmaps *res) -{ - struct mp_rect bb_list[MP_SUB_BB_LIST_MAX]; - int num_bb = mp_get_sub_bb_list(res, bb_list, MP_SUB_BB_LIST_MAX); - - struct sub_bitmaps imgs = { - .change_id = res->change_id, - .format = SUBBITMAP_BGRA, - .parts = p->rgba_imgs, - .num_parts = num_bb, - }; - - for (int n = 0; n < imgs.num_parts; n++) { - imgs.parts[n].w = bb_list[n].x1 - bb_list[n].x0; - imgs.parts[n].h = bb_list[n].y1 - bb_list[n].y0; - } - - if (!pack(p, &imgs, IMGFMT_BGRA)) - return false; - - int padding = p->packer->padding; - uint8_t *base = imgs.packed->planes[0]; - int stride = imgs.packed->stride[0]; - - for (int n = 0; n < num_bb; n++) { - struct mp_rect bb = bb_list[n]; - struct sub_bitmap *b = &imgs.parts[n]; - - b->x = bb.x0; - b->y = bb.y0; - b->w = b->dw = mp_rect_w(bb); - b->h = b->dh = mp_rect_h(bb); - b->stride = stride; - b->bitmap = base + b->stride * b->src_y + b->src_x * 4; - memset_pic(b->bitmap, 0, b->w * 4, b->h, b->stride); - - for (int i = 0; i < res->num_parts; i++) { - struct sub_bitmap *s = &res->parts[i]; - - // Assume mp_get_sub_bb_list() never splits sub bitmaps - // So we don't clip/adjust the size of the sub bitmap - if (s->x >= b->x + b->w || s->x + s->w <= b->x || - s->y >= b->y + b->h || s->y + s->h <= b->y) - continue; - - draw_ass_rgba(s->bitmap, s->w, s->h, s->stride, - b->bitmap, b->stride, - s->x - b->x, s->y - b->y, - s->libass.color); - } - fill_padding_4(b->bitmap, b->w, b->h, b->stride, padding); - } - - *res = imgs; - return true; -} - -// Pack the contents of image_lists[0] to image_lists[num_image_lists-1] into -// a single image, and make *out point to it. *out is completely overwritten. -// If libass reported any change, image_lists_changed must be set (it then -// repacks all images). preferred_osd_format can be set to a desired -// sub_bitmap_format. Currently, only SUBBITMAP_LIBASS is supported. -void mp_ass_packer_pack(struct mp_ass_packer *p, ASS_Image **image_lists, - int num_image_lists, bool image_lists_changed, bool video_color_space, - int preferred_osd_format, struct sub_bitmaps *out) -{ - int format = preferred_osd_format == SUBBITMAP_BGRA ? SUBBITMAP_BGRA - : SUBBITMAP_LIBASS; - - if (p->cached_subs_valid && !image_lists_changed && - p->cached_subs.format == format) - { - *out = p->cached_subs; - return; - } - - *out = (struct sub_bitmaps){.change_id = 1}; - p->cached_subs_valid = false; - - struct sub_bitmaps res = { - .change_id = image_lists_changed, - .format = SUBBITMAP_LIBASS, - .parts = p->cached_parts, - .video_color_space = video_color_space, - }; - - for (int n = 0; n < num_image_lists; n++) { - for (struct ass_image *img = image_lists[n]; img; img = img->next) { - if (img->w == 0 || img->h == 0) - continue; - MP_TARRAY_GROW(p, p->cached_parts, res.num_parts); - res.parts = p->cached_parts; - struct sub_bitmap *b = &res.parts[res.num_parts]; - b->bitmap = img->bitmap; - b->stride = img->stride; - b->libass.color = img->color; - b->dw = b->w = img->w; - b->dh = b->h = img->h; - b->x = img->dst_x; - b->y = img->dst_y; - res.num_parts++; - } - } - - bool r = false; - if (format == SUBBITMAP_BGRA) { - r = pack_rgba(p, &res); - } else { - r = pack_libass(p, &res); - } - - if (!r) - return; - - *out = res; - p->cached_subs = res; - p->cached_subs.change_id = 0; - p->cached_subs_valid = true; -} - // Set *out_rc to [x0, y0, x1, y1] of the graphical bounding box in script // coordinates. // Set it to [inf, inf, -inf, -inf] if empty. diff --git a/sub/ass_mp.h b/sub/ass_mp.h index b4e16d6650..ecc44231ec 100644 --- a/sub/ass_mp.h +++ b/sub/ass_mp.h @@ -20,7 +20,6 @@ #ifndef MPLAYER_ASS_MP_H #define MPLAYER_ASS_MP_H -#include #include #include @@ -53,12 +52,6 @@ void mp_ass_configure_fonts(ASS_Renderer *priv, struct osd_style_opts *opts, ASS_Library *mp_ass_init(struct mpv_global *global, struct osd_style_opts *opts, struct mp_log *log); -struct sub_bitmaps; -struct mp_ass_packer; -struct mp_ass_packer *mp_ass_packer_alloc(void *ta_parent); -void mp_ass_packer_pack(struct mp_ass_packer *p, ASS_Image **image_lists, - int num_image_lists, bool changed, bool video_color_space, - int preferred_osd_format, struct sub_bitmaps *out); void mp_ass_get_bb(ASS_Image *image_list, ASS_Track *track, struct mp_osd_res *res, double *out_rc); diff --git a/sub/osd_libass.c b/sub/osd_libass.c index 8e79bd8a2f..7b0850954c 100644 --- a/sub/osd_libass.c +++ b/sub/osd_libass.c @@ -33,6 +33,7 @@ static const char osd_font_pfb[] = ; #include "sub/ass_mp.h" +#include "sub/packer.h" #include "options/options.h" @@ -690,13 +691,13 @@ struct sub_bitmaps *osd_object_get_bitmaps(struct osd_state *osd, if (obj->osd_changed) { update_osd(osd, obj); } else { - mp_require(obj->ass_packer); + mp_require(obj->sub_packer); goto done; } } - if (!obj->ass_packer) - obj->ass_packer = mp_ass_packer_alloc(obj); + if (!obj->sub_packer) + obj->sub_packer = mp_sub_packer_alloc(obj); MP_TARRAY_GROW(obj, obj->ass_imgs, obj->num_externals + 1); @@ -713,7 +714,7 @@ struct sub_bitmaps *osd_object_get_bitmaps(struct osd_state *osd, done:; struct sub_bitmaps out_imgs = {0}; - mp_ass_packer_pack(obj->ass_packer, obj->ass_imgs, obj->num_externals + 1, + mp_sub_packer_pack_ass(obj->sub_packer, obj->ass_imgs, obj->num_externals + 1, obj->changed, false, format, &out_imgs); obj->changed = false; diff --git a/sub/osd_state.h b/sub/osd_state.h index ef0ff20a57..cd4ca15a04 100644 --- a/sub/osd_state.h +++ b/sub/osd_state.h @@ -55,7 +55,7 @@ struct osd_object { // Internally used by osd_libass.c bool changed; struct ass_state ass; - struct mp_ass_packer *ass_packer; + struct mp_sub_packer *sub_packer; struct sub_bitmap_copy_cache *copy_cache; struct ass_image **ass_imgs; }; diff --git a/sub/packer.c b/sub/packer.c new file mode 100644 index 0000000000..cfa41cbe5d --- /dev/null +++ b/sub/packer.c @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2006 Evgeniy Stepanov + * + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#include +#include +#include +#include + +#include "config.h" + +#include +#include + +#include "common/common.h" +#include "packer.h" +#include "img_convert.h" +#include "osd.h" +#include "video/out/bitmap_packer.h" +#include "video/mp_image.h" + +struct mp_sub_packer { + struct sub_bitmap *cached_parts; // only for the array memory + struct mp_image *cached_img; + struct sub_bitmaps cached_subs; + bool cached_subs_valid; + struct sub_bitmap rgba_imgs[MP_SUB_BB_LIST_MAX]; + struct bitmap_packer *packer; +}; + +// Free with talloc_free(). +struct mp_sub_packer *mp_sub_packer_alloc(void *ta_parent) +{ + struct mp_sub_packer *p = talloc_zero(ta_parent, struct mp_sub_packer); + p->packer = talloc_zero(p, struct bitmap_packer); + p->packer->padding = 1; // assume bilinear sampling + return p; +} + +static bool pack(struct mp_sub_packer *p, struct sub_bitmaps *res, int imgfmt) +{ + packer_set_size(p->packer, res->num_parts); + + for (int n = 0; n < res->num_parts; n++) + p->packer->in[n] = (struct pos){res->parts[n].w, res->parts[n].h}; + + if (p->packer->count == 0 || packer_pack(p->packer) < 0) + return false; + + struct pos bb[2]; + packer_get_bb(p->packer, bb); + + res->packed_w = bb[1].x; + res->packed_h = bb[1].y; + + if (!p->cached_img || p->cached_img->w < res->packed_w || + p->cached_img->h < res->packed_h || + p->cached_img->imgfmt != imgfmt) + { + talloc_free(p->cached_img); + p->cached_img = mp_image_alloc(imgfmt, p->packer->w, p->packer->h); + if (!p->cached_img) { + packer_reset(p->packer); + return false; + } + talloc_steal(p, p->cached_img); + } + + if (!mp_image_make_writeable(p->cached_img)) { + packer_reset(p->packer); + return false; + } + + res->packed = p->cached_img; + + for (int n = 0; n < res->num_parts; n++) { + struct sub_bitmap *b = &res->parts[n]; + struct pos pos = p->packer->result[n]; + + b->src_x = pos.x; + b->src_y = pos.y; + } + + return true; +} + +static void fill_padding_1(uint8_t *base, int w, int h, int stride, int padding) +{ + for (int row = 0; row < h; ++row) { + uint8_t *row_ptr = base + row * stride; + uint8_t left_pixel = row_ptr[0]; + uint8_t right_pixel = row_ptr[w - 1]; + + for (int i = 1; i <= padding; ++i) + row_ptr[-i] = left_pixel; + + for (int i = 0; i < padding; ++i) + row_ptr[w + i] = right_pixel; + } + + int row_bytes = (w + 2 * padding); + uint8_t *top_row = base - padding; + for (int i = 1; i <= padding; ++i) + memcpy(base - i * stride - padding, top_row, row_bytes); + + uint8_t *last_row = base + (h - 1) * stride - padding; + for (int i = 0; i < padding; ++i) + memcpy(base + (h + i) * stride - padding, last_row, row_bytes); +} + +static void fill_padding_4(uint8_t *base, int w, int h, int stride, int padding) +{ + for (int row = 0; row < h; ++row) { + uint32_t *row_ptr = (uint32_t *)(base + row * stride); + uint32_t left_pixel = row_ptr[0]; + uint32_t right_pixel = row_ptr[w - 1]; + + for (int i = 1; i <= padding; ++i) + row_ptr[-i] = left_pixel; + + for (int i = 0; i < padding; ++i) + row_ptr[w + i] = right_pixel; + } + + int row_bytes = (w + 2 * padding) * 4; + uint8_t *top_row = base - padding * 4; + for (int i = 1; i <= padding; ++i) + memcpy(base - i * stride - padding * 4, top_row, row_bytes); + + uint8_t *last_row = base + (h - 1) * stride - padding * 4; + for (int i = 0; i < padding; ++i) + memcpy(base + (h + i) * stride - padding * 4, last_row, row_bytes); +} + +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) +{ + const unsigned int r = (color >> 24) & 0xff; + const unsigned int g = (color >> 16) & 0xff; + const unsigned int b = (color >> 8) & 0xff; + const unsigned int a = 0xff - (color & 0xff); + + dst += dst_y * dst_stride + dst_x * 4; + + for (int y = 0; y < src_h; y++, dst += dst_stride, src += src_stride) { + uint32_t *dstrow = (uint32_t *) dst; + for (int x = 0; x < src_w; x++) { + const unsigned int v = src[x]; + int rr = (r * a * v); + int gg = (g * a * v); + int bb = (b * a * v); + int aa = a * v; + uint32_t dstpix = dstrow[x]; + unsigned int dstb = dstpix & 0xFF; + unsigned int dstg = (dstpix >> 8) & 0xFF; + unsigned int dstr = (dstpix >> 16) & 0xFF; + unsigned int dsta = (dstpix >> 24) & 0xFF; + dstb = (bb + dstb * (255 * 255 - aa)) / (255 * 255); + dstg = (gg + dstg * (255 * 255 - aa)) / (255 * 255); + dstr = (rr + dstr * (255 * 255 - aa)) / (255 * 255); + dsta = (aa * 255 + dsta * (255 * 255 - aa)) / (255 * 255); + dstrow[x] = dstb | (dstg << 8) | (dstr << 16) | (dsta << 24); + } + } +} + +static bool pack_libass(struct mp_sub_packer *p, struct sub_bitmaps *res) +{ + if (!pack(p, res, IMGFMT_Y8)) + return false; + + int padding = p->packer->padding; + uint8_t *base = res->packed->planes[0]; + int stride = res->packed->stride[0]; + + for (int n = 0; n < res->num_parts; n++) { + struct sub_bitmap *b = &res->parts[n]; + void *pdata = base + b->src_y * stride + b->src_x; + memcpy_pic(pdata, b->bitmap, b->w, b->h, stride, b->stride); + fill_padding_1(pdata, b->w, b->h, stride, padding); + + b->bitmap = pdata; + b->stride = stride; + } + + return true; +} + +static bool pack_rgba(struct mp_sub_packer *p, struct sub_bitmaps *res) +{ + struct mp_rect bb_list[MP_SUB_BB_LIST_MAX]; + int num_bb = mp_get_sub_bb_list(res, bb_list, MP_SUB_BB_LIST_MAX); + + struct sub_bitmaps imgs = { + .change_id = res->change_id, + .format = SUBBITMAP_BGRA, + .parts = p->rgba_imgs, + .num_parts = num_bb, + }; + + for (int n = 0; n < imgs.num_parts; n++) { + imgs.parts[n].w = bb_list[n].x1 - bb_list[n].x0; + imgs.parts[n].h = bb_list[n].y1 - bb_list[n].y0; + } + + if (!pack(p, &imgs, IMGFMT_BGRA)) + return false; + + int padding = p->packer->padding; + uint8_t *base = imgs.packed->planes[0]; + int stride = imgs.packed->stride[0]; + + for (int n = 0; n < num_bb; n++) { + struct mp_rect bb = bb_list[n]; + struct sub_bitmap *b = &imgs.parts[n]; + + b->x = bb.x0; + b->y = bb.y0; + b->w = b->dw = mp_rect_w(bb); + b->h = b->dh = mp_rect_h(bb); + b->stride = stride; + b->bitmap = base + b->stride * b->src_y + b->src_x * 4; + memset_pic(b->bitmap, 0, b->w * 4, b->h, b->stride); + + for (int i = 0; i < res->num_parts; i++) { + struct sub_bitmap *s = &res->parts[i]; + + // Assume mp_get_sub_bb_list() never splits sub bitmaps + // So we don't clip/adjust the size of the sub bitmap + if (s->x >= b->x + b->w || s->x + s->w <= b->x || + s->y >= b->y + b->h || s->y + s->h <= b->y) + continue; + + draw_ass_rgba(s->bitmap, s->w, s->h, s->stride, + b->bitmap, b->stride, + s->x - b->x, s->y - b->y, + s->libass.color); + } + fill_padding_4(b->bitmap, b->w, b->h, b->stride, padding); + } + + *res = imgs; + return true; +} + +// Pack the contents of image_lists[0] to image_lists[num_image_lists-1] into +// a single image, and make *out point to it. *out is completely overwritten. +// If libass reported any change, image_lists_changed must be set (it then +// repacks all images). preferred_osd_format can be set to a desired +// sub_bitmap_format. Currently, only SUBBITMAP_LIBASS is supported. +void mp_sub_packer_pack_ass(struct mp_sub_packer *p, ASS_Image **image_lists, + int num_image_lists, bool image_lists_changed, bool video_color_space, + int preferred_osd_format, struct sub_bitmaps *out) +{ + int format = preferred_osd_format == SUBBITMAP_BGRA ? SUBBITMAP_BGRA + : SUBBITMAP_LIBASS; + + if (p->cached_subs_valid && !image_lists_changed && + p->cached_subs.format == format) + { + *out = p->cached_subs; + return; + } + + *out = (struct sub_bitmaps){.change_id = 1}; + p->cached_subs_valid = false; + + struct sub_bitmaps res = { + .change_id = image_lists_changed, + .format = SUBBITMAP_LIBASS, + .parts = p->cached_parts, + .video_color_space = video_color_space, + }; + + for (int n = 0; n < num_image_lists; n++) { + for (struct ass_image *img = image_lists[n]; img; img = img->next) { + if (img->w == 0 || img->h == 0) + continue; + MP_TARRAY_GROW(p, p->cached_parts, res.num_parts); + res.parts = p->cached_parts; + struct sub_bitmap *b = &res.parts[res.num_parts]; + b->bitmap = img->bitmap; + b->stride = img->stride; + b->libass.color = img->color; + b->dw = b->w = img->w; + b->dh = b->h = img->h; + b->x = img->dst_x; + b->y = img->dst_y; + res.num_parts++; + } + } + + bool r = false; + if (format == SUBBITMAP_BGRA) { + r = pack_rgba(p, &res); + } else { + r = pack_libass(p, &res); + } + + if (!r) + return; + + *out = res; + p->cached_subs = res; + p->cached_subs.change_id = 0; + p->cached_subs_valid = true; +} diff --git a/sub/packer.h b/sub/packer.h new file mode 100644 index 0000000000..9b0a5c67ba --- /dev/null +++ b/sub/packer.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2006 Evgeniy Stepanov + * + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see . + */ + +#ifndef MP_SUB_PACKER_H +#define MP_SUB_PACKER_H + +#include + +#include +#include + +struct sub_bitmaps; +struct mp_sub_packer; +struct mp_sub_packer *mp_sub_packer_alloc(void *ta_parent); +void mp_sub_packer_pack_ass(struct mp_sub_packer *p, ASS_Image **image_lists, + int num_image_lists, bool changed, bool video_color_space, + int preferred_osd_format, struct sub_bitmaps *out); + +#endif diff --git a/sub/sd_ass.c b/sub/sd_ass.c index ece372a231..6c449ad442 100644 --- a/sub/sd_ass.c +++ b/sub/sd_ass.c @@ -38,6 +38,7 @@ #include "video/mp_image.h" #include "dec_sub.h" #include "ass_mp.h" +#include "packer.h" #include "sd.h" struct sd_ass_priv { @@ -51,7 +52,7 @@ struct sd_ass_priv { struct sd_filter **filters; int num_filters; bool clear_once; - struct mp_ass_packer *packer; + struct mp_sub_packer *packer; struct sub_bitmap_copy_cache *copy_cache; bstr last_text; struct mp_image_params video_params; @@ -319,7 +320,7 @@ static int init(struct sd *sd) assobjects_init(sd); filters_init(sd); - ctx->packer = mp_ass_packer_alloc(ctx); + ctx->packer = mp_sub_packer_alloc(ctx); // Subtitles does not have any profile value, so put the converted type as a profile. const char *_Atomic *desc = ctx->converter ? &sd->codec->codec_profile : &sd->codec->codec_desc; @@ -778,7 +779,7 @@ static struct sub_bitmaps *get_bitmaps(struct sd *sd, struct mp_osd_res dim, int changed; ASS_Image *imgs = ass_render_frame(renderer, track, ts, &changed); - mp_ass_packer_pack(ctx->packer, &imgs, 1, changed, !converted, format, res); + mp_sub_packer_pack_ass(ctx->packer, &imgs, 1, changed, !converted, format, res); done: // mangle_colors() modifies the color field, so copy the thing _before_.