diff options
-rw-r--r-- | libass/ass.h | 11 | ||||
-rw-r--r-- | libass/ass_cache.c | 6 | ||||
-rw-r--r-- | libass/ass_cache.h | 1 | ||||
-rw-r--r-- | libass/ass_render.c | 44 | ||||
-rw-r--r-- | libass/libass.sym | 1 |
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 |