summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libass/ass.h11
-rw-r--r--libass/ass_cache.c6
-rw-r--r--libass/ass_cache.h1
-rw-r--r--libass/ass_render.c44
-rw-r--r--libass/libass.sym1
5 files changed, 58 insertions, 5 deletions
diff --git a/libass/ass.h b/libass/ass.h
index 6efcc0f..b92960a 100644
--- a/libass/ass.h
+++ b/libass/ass.h
@@ -202,6 +202,17 @@ void ass_set_fonts(ass_renderer_t *priv, const char *default_font,
int ass_fonts_update(ass_renderer_t *priv);
/**
+ * \brief Set hard cache limits. Do not set, or set to zero, for reasonable
+ * defaults.
+ *
+ * \param priv renderer handle
+ * \param glyph_max maximum number of cached glyphs
+ * \param bitmap_max_size maximum bitmap cache size (in MB)
+ */
+void ass_set_cache_limits(ass_renderer_t *priv, int glyph_max,
+ int bitmap_max_size);
+
+/**
* \brief Render a frame, producing a list of ass_image_t.
* \param priv renderer handle
* \param track subtitle track
diff --git a/libass/ass_cache.c b/libass/ass_cache.c
index 4c7a3fa..524a1c8 100644
--- a/libass/ass_cache.c
+++ b/libass/ass_cache.c
@@ -223,6 +223,12 @@ static void bitmap_hash_dtor(void *key, size_t key_size, void *value,
void *cache_add_bitmap(hashmap_t *bitmap_cache, bitmap_hash_key_t *key,
bitmap_hash_val_t *val)
{
+ // Note: this is only an approximation
+ if (val->bm_o)
+ bitmap_cache->cache_size += val->bm_o->w * val->bm_o->h * 3;
+ else
+ bitmap_cache->cache_size += val->bm->w * val->bm->h * 3;
+
return hashmap_insert(bitmap_cache, key, val);
}
diff --git a/libass/ass_cache.h b/libass/ass_cache.h
index 83c9943..e31d8cf 100644
--- a/libass/ass_cache.h
+++ b/libass/ass_cache.h
@@ -45,6 +45,7 @@ typedef struct hashmap_s {
hashmap_item_dtor_t item_dtor; // a destructor for hashmap key/value pairs
hashmap_key_compare_t key_compare;
hashmap_hash_t hash;
+ size_t cache_size;
// stats
int hit_count;
int miss_count;
diff --git a/libass/ass_render.c b/libass/ass_render.c
index 5caf8eb..aeeb0ac 100644
--- a/libass/ass_render.c
+++ b/libass/ass_render.c
@@ -44,6 +44,8 @@
#define MAX_BE 127
#define SUBPIXEL_MASK 63
#define SUBPIXEL_ACCURACY 7 // d6 mask for subpixel accuracy adjustment
+#define GLYPH_CACHE_MAX 1000
+#define BITMAP_CACHE_MAX_SIZE 50 * 1048576;
static int last_render_id = 0;
@@ -206,6 +208,8 @@ typedef struct cache_store_s {
hashmap_t *glyph_cache;
hashmap_t *bitmap_cache;
hashmap_t *composite_cache;
+ size_t glyph_max;
+ size_t bitmap_max_size;
} cache_store_t;
struct ass_renderer_s {
@@ -319,6 +323,8 @@ ass_renderer_t *ass_renderer_init(ass_library_t *library)
priv->cache.bitmap_cache = ass_bitmap_cache_init(library);
priv->cache.composite_cache = ass_composite_cache_init(library);
priv->cache.glyph_cache = ass_glyph_cache_init(library);
+ priv->cache.glyph_max = GLYPH_CACHE_MAX;
+ priv->cache.bitmap_max_size = BITMAP_CACHE_MAX_SIZE;
priv->text_info.max_glyphs = MAX_GLYPHS_INITIAL;
priv->text_info.max_lines = MAX_LINES_INITIAL;
@@ -335,6 +341,14 @@ ass_renderer_t *ass_renderer_init(ass_library_t *library)
return priv;
}
+void ass_set_cache_limits(ass_renderer_t *render_priv, int glyph_max,
+ int bitmap_max)
+{
+ render_priv->cache.glyph_max = glyph_max ? glyph_max : GLYPH_CACHE_MAX;
+ render_priv->cache.bitmap_max_size = bitmap_max ? 1048576 * bitmap_max :
+ BITMAP_CACHE_MAX_SIZE;
+}
+
static void free_list_clear(ass_renderer_t *render_priv)
{
if (render_priv->free_head) {
@@ -2873,6 +2887,7 @@ ass_render_event(ass_renderer_t *render_priv, ass_event_t *event,
}
}
+
if (text_info->length == 0) {
// no valid symbols in the event; this can be smth like {comment}
free_render_context(render_priv);
@@ -3223,17 +3238,18 @@ static int
ass_start_frame(ass_renderer_t *render_priv, ass_track_t *track,
long long now)
{
- if (render_priv->library != track->library)
- return 1;
-
- free_list_clear(render_priv);
-
ass_settings_t *settings_priv = &render_priv->settings;
+ cache_store_t *cache = &render_priv->cache;
if (!render_priv->settings.frame_width
&& !render_priv->settings.frame_height)
return 1; // library not initialized
+ if (render_priv->library != track->library)
+ return 1;
+
+ free_list_clear(render_priv);
+
if (track->n_events == 0)
return 1; // nothing to do
@@ -3274,6 +3290,24 @@ ass_start_frame(ass_renderer_t *render_priv, ass_track_t *track,
render_priv->prev_images_root = render_priv->images_root;
render_priv->images_root = 0;
+ if (cache->bitmap_cache->cache_size > cache->bitmap_max_size) {
+ ass_msg(render_priv->library, MSGL_V,
+ "Hitting hard bitmap cache limit (was: %ld bytes), "
+ "resetting.", (long) cache->bitmap_cache->cache_size);
+ cache->bitmap_cache = ass_bitmap_cache_reset(cache->bitmap_cache);
+ cache->composite_cache = ass_composite_cache_reset(
+ cache->composite_cache);
+ ass_free_images(render_priv->prev_images_root);
+ render_priv->prev_images_root = 0;
+ }
+
+ if (cache->glyph_cache->count > cache->glyph_max) {
+ ass_msg(render_priv->library, MSGL_V,
+ "Hitting hard glyph cache limit (was: %ld glyphs), resetting.",
+ (long) cache->glyph_cache->count);
+ cache->glyph_cache = ass_glyph_cache_reset(cache->glyph_cache);
+ }
+
return 0;
}
diff --git a/libass/libass.sym b/libass/libass.sym
index c702842..e813a18 100644
--- a/libass/libass.sym
+++ b/libass/libass.sym
@@ -32,3 +32,4 @@ ass_step_sub
ass_process_force_style
ass_set_message_cb
ass_fonts_update
+ass_set_cache_limits