summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--player/command.c3
-rw-r--r--sub/ass_mp.c5
-rw-r--r--sub/dec_sub.c31
-rw-r--r--sub/dec_sub.h6
-rw-r--r--sub/draw_bmp.c17
-rw-r--r--sub/draw_bmp.h3
-rw-r--r--sub/osd.c172
-rw-r--r--sub/osd.h15
-rw-r--r--sub/osd_libass.c9
-rw-r--r--sub/osd_state.h7
-rw-r--r--sub/sd.h4
-rw-r--r--sub/sd_ass.c22
-rw-r--r--sub/sd_lavc.c13
13 files changed, 197 insertions, 110 deletions
diff --git a/player/command.c b/player/command.c
index a5105ffe92..2c44a3f095 100644
--- a/player/command.c
+++ b/player/command.c
@@ -4017,6 +4017,9 @@ static void recreate_overlays(struct MPContext *mpctx)
goto done;
}
+ if (!mp_image_make_writeable(new->packed))
+ goto done;
+
// clear padding
mp_image_clear(new->packed, 0, 0, new->packed->w, new->packed->h);
diff --git a/sub/ass_mp.c b/sub/ass_mp.c
index 172701495f..45328fb920 100644
--- a/sub/ass_mp.c
+++ b/sub/ass_mp.c
@@ -240,6 +240,11 @@ static bool pack(struct mp_ass_packer *p, struct sub_bitmaps *res, int imgfmt)
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++) {
diff --git a/sub/dec_sub.c b/sub/dec_sub.c
index 3842235c46..76e96bc16b 100644
--- a/sub/dec_sub.c
+++ b/sub/dec_sub.c
@@ -109,16 +109,6 @@ static double pts_from_subtitle(struct dec_sub *sub, double pts)
return pts;
}
-void sub_lock(struct dec_sub *sub)
-{
- pthread_mutex_lock(&sub->lock);
-}
-
-void sub_unlock(struct dec_sub *sub)
-{
- pthread_mutex_unlock(&sub->lock);
-}
-
static void wakeup_demux(void *ctx)
{
struct mp_dispatch_queue *q = ctx;
@@ -335,12 +325,12 @@ bool sub_read_packets(struct dec_sub *sub, double video_pts)
return r;
}
-// You must call sub_lock/sub_unlock if more than 1 thread access sub.
-// The issue is that *res will contain decoder allocated data, which might
-// be deallocated on the next decoder access.
-void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, int format,
- double pts, struct sub_bitmaps *res)
+// Unref sub_bitmaps.rc to free the result. May return NULL.
+struct sub_bitmaps *sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim,
+ int format, double pts)
{
+ pthread_mutex_lock(&sub->lock);
+
struct mp_subtitle_opts *opts = sub->opts;
pts = pts_to_subtitle(sub, pts);
@@ -348,11 +338,14 @@ void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, int format,
sub->last_vo_pts = pts;
update_segment(sub);
- if (sub->end != MP_NOPTS_VALUE && pts >= sub->end)
- return;
+ struct sub_bitmaps *res = NULL;
- if (opts->sub_visibility && sub->sd->driver->get_bitmaps)
- sub->sd->driver->get_bitmaps(sub->sd, dim, format, pts, res);
+ if (!(sub->end != MP_NOPTS_VALUE && pts >= sub->end) &&
+ opts->sub_visibility && sub->sd->driver->get_bitmaps)
+ res = sub->sd->driver->get_bitmaps(sub->sd, dim, format, pts);
+
+ pthread_mutex_unlock(&sub->lock);
+ return res;
}
// See sub_get_bitmaps() for locking requirements.
diff --git a/sub/dec_sub.h b/sub/dec_sub.h
index 030b8d21e1..8d0c76cd14 100644
--- a/sub/dec_sub.h
+++ b/sub/dec_sub.h
@@ -35,14 +35,12 @@ struct attachment_list {
struct dec_sub *sub_create(struct mpv_global *global, struct sh_stream *sh,
struct attachment_list *attachments);
void sub_destroy(struct dec_sub *sub);
-void sub_lock(struct dec_sub *sub);
-void sub_unlock(struct dec_sub *sub);
bool sub_can_preload(struct dec_sub *sub);
void sub_preload(struct dec_sub *sub);
bool sub_read_packets(struct dec_sub *sub, double video_pts);
-void sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim, int format,
- double pts, struct sub_bitmaps *res);
+struct sub_bitmaps *sub_get_bitmaps(struct dec_sub *sub, struct mp_osd_res dim,
+ int format, double pts);
char *sub_get_text(struct dec_sub *sub, double pts);
struct sd_times sub_get_times(struct dec_sub *sub, double pts);
void sub_reset(struct dec_sub *sub);
diff --git a/sub/draw_bmp.c b/sub/draw_bmp.c
index 0c913c86fd..ba027838ec 100644
--- a/sub/draw_bmp.c
+++ b/sub/draw_bmp.c
@@ -494,11 +494,8 @@ static void chroma_down(struct mp_image *old_src, struct mp_image *temp)
}
}
-// cache: if not NULL, the function will set *cache to a talloc-allocated cache
-// containing scaled versions of sbs contents - free the cache with
-// talloc_free()
-void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst,
- struct sub_bitmaps *sbs)
+static void draw_sbs(struct mp_draw_sub_cache **cache, struct mp_image *dst,
+ struct sub_bitmaps *sbs)
{
assert(mp_draw_sub_formats[sbs->format]);
if (!mp_sws_supported_format(dst->imgfmt))
@@ -542,4 +539,14 @@ void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst,
}
}
+// cache: if not NULL, the function will set *cache to a talloc-allocated cache
+// containing scaled versions of sbs contents - free the cache with
+// talloc_free()
+void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst,
+ struct sub_bitmap_list *sbs_list)
+{
+ for (int n = 0; n < sbs_list->num_items; n++)
+ draw_sbs(cache, dst, sbs_list->items[n]);
+}
+
// vim: ts=4 sw=4 et tw=80
diff --git a/sub/draw_bmp.h b/sub/draw_bmp.h
index 11fbd0daa0..6adfd2c6c5 100644
--- a/sub/draw_bmp.h
+++ b/sub/draw_bmp.h
@@ -4,10 +4,9 @@
#include "osd.h"
struct mp_image;
-struct sub_bitmaps;
struct mp_draw_sub_cache;
void mp_draw_sub_bitmaps(struct mp_draw_sub_cache **cache, struct mp_image *dst,
- struct sub_bitmaps *sbs);
+ struct sub_bitmap_list *sbs_list);
extern const bool mp_draw_sub_formats[SUBBITMAP_COUNT];
diff --git a/sub/osd.c b/sub/osd.c
index 93e1a07162..87f9186d21 100644
--- a/sub/osd.c
+++ b/sub/osd.c
@@ -152,6 +152,7 @@ void osd_free(struct osd_state *osd)
if (!osd)
return;
osd_destroy_backend(osd);
+ talloc_free(osd->objs[OSDTYPE_EXTERNAL2]->external2);
pthread_mutex_destroy(&osd->lock);
talloc_free(osd);
}
@@ -233,8 +234,10 @@ void osd_set_progbar(struct osd_state *osd, struct osd_progbar_state *s)
void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs)
{
pthread_mutex_lock(&osd->lock);
- osd->objs[OSDTYPE_EXTERNAL2]->external2 = imgs;
- osd->objs[OSDTYPE_EXTERNAL2]->vo_change_id += 1;
+ struct osd_object *obj = osd->objs[OSDTYPE_EXTERNAL2];
+ talloc_free(obj->external2);
+ obj->external2 = sub_bitmaps_copy(NULL, imgs);
+ obj->vo_change_id += 1;
osd->want_redraw_notification = true;
pthread_mutex_unlock(&osd->lock);
}
@@ -265,48 +268,53 @@ void osd_resize(struct osd_state *osd, struct mp_osd_res res)
pthread_mutex_unlock(&osd->lock);
}
-static void render_object(struct osd_state *osd, struct osd_object *obj,
- struct mp_osd_res res, double video_pts,
- const bool sub_formats[SUBBITMAP_COUNT],
- struct sub_bitmaps *out_imgs)
+static struct sub_bitmaps *render_object(struct osd_state *osd,
+ struct osd_object *obj,
+ struct mp_osd_res osdres, double video_pts,
+ const bool sub_formats[SUBBITMAP_COUNT])
{
int format = SUBBITMAP_LIBASS;
if (!sub_formats[format] || osd->opts->force_rgba_osd)
format = SUBBITMAP_RGBA;
- *out_imgs = (struct sub_bitmaps) {0};
+ struct sub_bitmaps *res = NULL;
- check_obj_resize(osd, res, obj);
+ check_obj_resize(osd, osdres, obj);
if (obj->type == OSDTYPE_SUB || obj->type == OSDTYPE_SUB2) {
if (obj->sub)
- sub_get_bitmaps(obj->sub, obj->vo_res, format, video_pts, out_imgs);
+ res = sub_get_bitmaps(obj->sub, obj->vo_res, format, video_pts);
} else if (obj->type == OSDTYPE_EXTERNAL2) {
if (obj->external2 && obj->external2->format) {
- *out_imgs = *obj->external2;
+ res = sub_bitmaps_copy(NULL, obj->external2); // need to be owner
obj->external2->change_id = 0;
}
} else {
- osd_object_get_bitmaps(osd, obj, format, out_imgs);
+ res = osd_object_get_bitmaps(osd, obj, format);
}
- obj->vo_change_id += out_imgs->change_id;
+ if (res) {
+ obj->vo_change_id += res->change_id;
- if (out_imgs->num_parts == 0)
- return;
+ res->render_index = obj->type;
+ res->change_id = obj->vo_change_id;
+ }
- out_imgs->render_index = obj->type;
- out_imgs->change_id = obj->vo_change_id;
+ return res;
}
+// Render OSD to a list of bitmap and return it. The returned object is
+// refcounted. Typically you should hold it only for a short time, and then
+// release it.
// draw_flags is a bit field of OSD_DRAW_* constants
-void osd_draw(struct osd_state *osd, struct mp_osd_res res,
- double video_pts, int draw_flags,
- const bool formats[SUBBITMAP_COUNT],
- void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx)
+struct sub_bitmap_list *osd_render(struct osd_state *osd, struct mp_osd_res res,
+ double video_pts, int draw_flags,
+ const bool formats[SUBBITMAP_COUNT])
{
pthread_mutex_lock(&osd->lock);
+ struct sub_bitmap_list *list = talloc_zero(NULL, struct sub_bitmap_list);
+
if (osd->force_video_pts != MP_NOPTS_VALUE)
video_pts = osd->force_video_pts;
@@ -325,31 +333,26 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res,
if ((draw_flags & OSD_DRAW_OSD_ONLY) && obj->is_sub)
continue;
- if (obj->sub)
- sub_lock(obj->sub);
-
char *stat_type_render = obj->is_sub ? "sub-render" : "osd-render";
- char *stat_type_draw = obj->is_sub ? "sub-draw" : "osd-draw";
stats_time_start(osd->stats, stat_type_render);
- struct sub_bitmaps imgs;
- render_object(osd, obj, res, video_pts, formats, &imgs);
+ struct sub_bitmaps *imgs =
+ render_object(osd, obj, res, video_pts, formats);
stats_time_end(osd->stats, stat_type_render);
- if (imgs.num_parts > 0) {
- if (formats[imgs.format]) {
- stats_time_start(osd->stats, stat_type_draw);
- cb(cb_ctx, &imgs);
- stats_time_end(osd->stats, stat_type_draw);
+ if (imgs && imgs->num_parts > 0) {
+ if (formats[imgs->format]) {
+ talloc_steal(list, imgs);
+ MP_TARRAY_APPEND(list, list->items, list->num_items, imgs);
+ imgs = NULL;
} else {
MP_ERR(osd, "Can't render OSD part %d (format %d).\n",
- obj->type, imgs.format);
+ obj->type, imgs->format);
}
}
- if (obj->sub)
- sub_unlock(obj->sub);
+ talloc_free(imgs);
}
// If this is called with OSD_DRAW_SUB_ONLY or OSD_DRAW_OSD_ONLY set, assume
@@ -360,35 +363,34 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res,
osd->want_redraw_notification = false;
pthread_mutex_unlock(&osd->lock);
+ return list;
}
-struct draw_on_image_closure {
- struct osd_state *osd;
- struct mp_image *dest;
- struct mp_image_pool *pool;
- bool changed;
-};
-
-static void draw_on_image(void *ctx, struct sub_bitmaps *imgs)
+// Warning: this function should be considered legacy. Use osd_render() instead.
+void osd_draw(struct osd_state *osd, struct mp_osd_res res,
+ double video_pts, int draw_flags,
+ const bool formats[SUBBITMAP_COUNT],
+ void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx)
{
- struct draw_on_image_closure *closure = ctx;
- struct osd_state *osd = closure->osd;
- if (!mp_image_pool_make_writeable(closure->pool, closure->dest))
- return; // on OOM, skip
- mp_draw_sub_bitmaps(&osd->draw_cache, closure->dest, imgs);
- talloc_steal(osd, osd->draw_cache);
- closure->changed = true;
+ struct sub_bitmap_list *list =
+ osd_render(osd, res, video_pts, draw_flags, formats);
+
+ stats_time_start(osd->stats, "draw");
+
+ for (int n = 0; n < list->num_items; n++)
+ cb(cb_ctx, list->items[n]);
+
+ stats_time_end(osd->stats, "draw");
+
+ talloc_free(list);
}
// Calls mp_image_make_writeable() on the dest image if something is drawn.
-// Returns whether anything was drawn.
-bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res,
+// draw_flags as in osd_render().
+void osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags, struct mp_image *dest)
{
- struct draw_on_image_closure closure = {osd, dest};
- osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats,
- &draw_on_image, &closure);
- return closure.changed;
+ osd_draw_on_image_p(osd, res, video_pts, draw_flags, NULL, dest);
}
// Like osd_draw_on_image(), but if dest needs to be copied to make it
@@ -398,9 +400,26 @@ void osd_draw_on_image_p(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags,
struct mp_image_pool *pool, struct mp_image *dest)
{
- struct draw_on_image_closure closure = {osd, dest, pool};
- osd_draw(osd, res, video_pts, draw_flags, mp_draw_sub_formats,
- &draw_on_image, &closure);
+ struct sub_bitmap_list *list =
+ osd_render(osd, res, video_pts, draw_flags, mp_draw_sub_formats);
+
+ if (!list->num_items) {
+ talloc_free(list);
+ return;
+ }
+
+ if (!mp_image_pool_make_writeable(pool, dest))
+ return; // on OOM, skip
+
+ // Need to lock for the dumb osd->draw_cache thing.
+ pthread_mutex_lock(&osd->lock);
+
+ mp_draw_sub_bitmaps(&osd->draw_cache, dest, list);
+ talloc_steal(osd, osd->draw_cache);
+
+ pthread_mutex_unlock(&osd->lock);
+
+ talloc_free(list);
}
// Setup the OSD resolution to render into an image with the given parameters.
@@ -471,3 +490,40 @@ void osd_rescale_bitmaps(struct sub_bitmaps *imgs, int frame_w, int frame_h,
bi->dh = (int)(bi->h * yscale + 0.5);
}
}
+
+// Copy *in and return a new allocation of it. Free with talloc_free(). This
+// will contain a refcounted copy of the image data.
+//
+// in->packed must be set and must be a refcounted image, unless there is no
+// data (num_parts==0).
+//
+// p_cache: if not NULL, then this points to a struct sub_bitmap_copy_cache*
+// variable. The function may set this to an allocation and may later
+// read it. You have to free it with talloc_free() when done.
+// in: valid struct, or NULL (in this case it also returns NULL)
+// returns: new copy, or NULL if there was no data in the input
+struct sub_bitmaps *sub_bitmaps_copy(struct sub_bitmap_copy_cache **p_cache,
+ struct sub_bitmaps *in)
+{
+ if (!in || !in->num_parts)
+ return NULL;
+
+ struct sub_bitmaps *res = talloc(NULL, struct sub_bitmaps);
+ *res = *in;
+
+ // Note: the p_cache thing is a lie and unused.
+
+ // The bitmaps being refcounted is essential for performance, and for
+ // not invalidating in->parts[*].bitmap pointers.
+ assert(in->packed && in->packed->bufs[0]);
+
+ res->packed = mp_image_new_ref(res->packed);
+ MP_HANDLE_OOM(res->packed);
+ talloc_steal(res, res->packed);
+
+ res->parts = NULL;
+ MP_RESIZE_ARRAY(res, res->parts, res->num_parts);
+ memcpy(res->parts, in->parts, sizeof(res->parts[0]) * res->num_parts);
+
+ return res;
+}
diff --git a/sub/osd.h b/sub/osd.h
index 5a6809817f..207d789094 100644
--- a/sub/osd.h
+++ b/sub/osd.h
@@ -76,6 +76,15 @@ struct sub_bitmaps {
int change_id; // Incremented on each change
};
+struct sub_bitmap_list {
+ struct sub_bitmaps **items;
+ int num_items;
+};
+
+struct sub_bitmap_copy_cache;
+struct sub_bitmaps *sub_bitmaps_copy(struct sub_bitmap_copy_cache **cache,
+ struct sub_bitmaps *in);
+
struct mp_osd_res {
int w, h; // screen dimensions, including black borders
int mt, mb, ml, mr; // borders (top, bottom, left, right)
@@ -183,8 +192,12 @@ void osd_draw(struct osd_state *osd, struct mp_osd_res res,
const bool formats[SUBBITMAP_COUNT],
void (*cb)(void *ctx, struct sub_bitmaps *imgs), void *cb_ctx);
+struct sub_bitmap_list *osd_render(struct osd_state *osd, struct mp_osd_res res,
+ double video_pts, int draw_flags,
+ const bool formats[SUBBITMAP_COUNT]);
+
struct mp_image;
-bool osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res,
+void osd_draw_on_image(struct osd_state *osd, struct mp_osd_res res,
double video_pts, int draw_flags, struct mp_image *dest);
struct mp_image_pool;
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index bf527e17f3..9aac0eb3ae 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -634,8 +634,8 @@ static void append_ass(struct ass_state *ass, struct mp_osd_res *res,
}
}
-void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
- int format, struct sub_bitmaps *out_imgs)
+struct sub_bitmaps *osd_object_get_bitmaps(struct osd_state *osd,
+ struct osd_object *obj, int format)
{
if (obj->type == OSDTYPE_OSD && obj->osd_changed)
update_osd(osd, obj);
@@ -656,8 +656,11 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
}
}
+ struct sub_bitmaps out_imgs = {0};
mp_ass_packer_pack(obj->ass_packer, obj->ass_imgs, obj->num_externals + 1,
- obj->changed, format, out_imgs);
+ obj->changed, format, &out_imgs);
obj->changed = false;
+
+ return sub_bitmaps_copy(&obj->copy_cache, &out_imgs);
}
diff --git a/sub/osd_state.h b/sub/osd_state.h
index 3469f4383d..054a98775b 100644
--- a/sub/osd_state.h
+++ b/sub/osd_state.h
@@ -54,6 +54,7 @@ struct osd_object {
bool changed;
struct ass_state ass;
struct mp_ass_packer *ass_packer;
+ struct sub_bitmap_copy_cache *copy_cache;
struct ass_image **ass_imgs;
};
@@ -82,9 +83,9 @@ struct osd_state {
struct mp_draw_sub_cache *draw_cache;
};
-// defined in osd_libass.c and osd_dummy.c
-void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj,
- int format, struct sub_bitmaps *out_imgs);
+// defined in osd_libass.c
+struct sub_bitmaps *osd_object_get_bitmaps(struct osd_state *osd,
+ struct osd_object *obj, int format);
void osd_init_backend(struct osd_state *osd);
void osd_destroy_backend(struct osd_state *osd);
diff --git a/sub/sd.h b/sub/sd.h
index a3085be864..d3d70bf594 100644
--- a/sub/sd.h
+++ b/sub/sd.h
@@ -38,8 +38,8 @@ struct sd_functions {
bool (*accepts_packet)(struct sd *sd, double pts); // implicit default if NULL: true
int (*control)(struct sd *sd, enum sd_ctrl cmd, void *arg);
- void (*get_bitmaps)(struct sd *sd, struct mp_osd_res dim, int format,
- double pts, struct sub_bitmaps *res);
+ struct sub_bitmaps *(*get_bitmaps)(struct sd *sd, struct mp_osd_res dim,
+ int format, double pts);
char *(*get_text)(struct sd *sd, double pts);
struct sd_times (*get_times)(struct sd *sd, double pts);
};
diff --git a/sub/sd_ass.c b/sub/sd_ass.c
index 40e5093d8e..d51f892dd4 100644
--- a/sub/sd_ass.c
+++ b/sub/sd_ass.c
@@ -50,7 +50,7 @@ struct sd_ass_priv {
bool clear_once;
bool on_top;
struct mp_ass_packer *packer;
- struct sub_bitmap *bs;
+ struct sub_bitmap_copy_cache *copy_cache;
char last_text[500];
struct mp_image_params video_params;
struct mp_image_params last_params;
@@ -498,8 +498,8 @@ static long long find_timestamp(struct sd *sd, double pts)
#undef END
-static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, int format,
- double pts, struct sub_bitmaps *res)
+static struct sub_bitmaps *get_bitmaps(struct sd *sd, struct mp_osd_res dim,
+ int format, double pts)
{
struct sd_ass_priv *ctx = sd->priv;
struct mp_subtitle_opts *opts = sd->opts;
@@ -508,9 +508,10 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, int format,
bool converted = ctx->is_converted || no_ass;
ASS_Track *track = no_ass ? ctx->shadow_track : ctx->ass_track;
ASS_Renderer *renderer = ctx->ass_renderer;
+ struct sub_bitmaps *res = &(struct sub_bitmaps){0};
if (pts == MP_NOPTS_VALUE || !renderer)
- return;
+ goto done;
double scale = dim.display_par;
if (!converted && (!opts->ass_style_override ||
@@ -544,14 +545,14 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res dim, int format,
ASS_Image *imgs = ass_render_frame(renderer, track, ts, &changed);
mp_ass_packer_pack(ctx->packer, &imgs, 1, changed, format, res);
- if (!converted && res->num_parts > 0) {
- // mangle_colors() modifies the color field, so copy the thing.
- MP_TARRAY_GROW(ctx, ctx->bs, res->num_parts);
- memcpy(ctx->bs, res->parts, sizeof(ctx->bs[0]) * res->num_parts);
- res->parts = ctx->bs;
+done:
+ // mangle_colors() modifies the color field, so copy the thing _before_.
+ res = sub_bitmaps_copy(&ctx->copy_cache, res);
+ if (!converted && res)
mangle_colors(sd, res);
- }
+
+ return res;
}
struct buf {
@@ -752,6 +753,7 @@ static void uninit(struct sd *sd)
ass_free_track(ctx->shadow_track);
enable_output(sd, false);
ass_library_done(ctx->ass_library);
+ talloc_free(ctx->copy_cache);
}
static int control(struct sd *sd, enum sd_ctrl cmd, void *arg)
diff --git a/sub/sd_lavc.c b/sub/sd_lavc.c
index 3d2f137dd3..620b3f85a7 100644
--- a/sub/sd_lavc.c
+++ b/sub/sd_lavc.c
@@ -226,6 +226,11 @@ static void read_sub_bitmaps(struct sd *sd, struct sub *sub)
talloc_steal(priv, sub->data);
}
+ if (!mp_image_make_writeable(sub->data)) {
+ sub->count = 0;
+ return;
+ }
+
for (int i = 0; i < sub->count; i++) {
struct sub_bitmap *b = &sub->inbitmaps[i];
struct pos pos = priv->packer->result[i];
@@ -400,8 +405,8 @@ static struct sub *get_current(struct sd_lavc_priv *priv, double pts)
return current;
}
-static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
- double pts, struct sub_bitmaps *res)
+static struct sub_bitmaps *get_bitmaps(struct sd *sd, struct mp_osd_res d,
+ int format, double pts)
{
struct sd_lavc_priv *priv = sd->priv;
struct mp_subtitle_opts *opts = sd->opts;
@@ -411,12 +416,13 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
struct sub *current = get_current(priv, pts);
if (!current)
- return;
+ return NULL;
MP_TARRAY_GROW(priv, priv->outbitmaps, current->count);
for (int n = 0; n < current->count; n++)
priv->outbitmaps[n] = current->inbitmaps[n];
+ struct sub_bitmaps *res = &(struct sub_bitmaps){0};
res->parts = priv->outbitmaps;
res->num_parts = current->count;
if (priv->displayed_id != current->id)
@@ -484,6 +490,7 @@ static void get_bitmaps(struct sd *sd, struct mp_osd_res d, int format,
}
}
+ return sub_bitmaps_copy(NULL, res);
}
static struct sd_times get_times(struct sd *sd, double pts)