Mercurial > mplayer.hg
annotate libass/ass_cache.c @ 32439:2f1ccd169a7f
Improve vd_ffmpeg aspect handling to respect container aspect if possible
(i.e. until the first resolution or aspect change) and to use correct
aspect if only resolution changes but not the pixel aspect.
author | reimar |
---|---|
date | Fri, 22 Oct 2010 17:36:11 +0000 |
parents | e64df5862cea |
children | 88eebbbbd6a0 |
rev | line source |
---|---|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
1 /* |
26723 | 2 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
3 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
4 * This file is part of libass. |
26723 | 5 * |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
6 * libass is free software; you can redistribute it and/or modify |
26723 | 7 * it under the terms of the GNU General Public License as published by |
8 * the Free Software Foundation; either version 2 of the License, or | |
9 * (at your option) any later version. | |
10 * | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
11 * libass is distributed in the hope that it will be useful, |
26723 | 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 * GNU General Public License for more details. | |
15 * | |
16 * You should have received a copy of the GNU General Public License along | |
26738
588ce97b44f2
Speak of libass instead of MPlayer in the libass license headers.
diego
parents:
26723
diff
changeset
|
17 * with libass; if not, write to the Free Software Foundation, Inc., |
26723 | 18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 */ | |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19965
diff
changeset
|
20 |
18937 | 21 #include "config.h" |
22 | |
22292 | 23 #include <inttypes.h> |
18937 | 24 #include <ft2build.h> |
25 #include FT_FREETYPE_H | |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
26 #include FT_GLYPH_H |
18937 | 27 |
28 #include <assert.h> | |
29 | |
30200 | 30 #include "ass_utils.h" |
21458
7af6c25a0cfc
Keep embedded fonts in ass_library_t and perform actual disk write
eugeni
parents:
21348
diff
changeset
|
31 #include "ass.h" |
18937 | 32 #include "ass_fontconfig.h" |
21322 | 33 #include "ass_font.h" |
19846
bcc792bfa431
Store bitmap glyphs in a separate struct, instead of FreeType's internal buffer.
eugeni
parents:
19545
diff
changeset
|
34 #include "ass_bitmap.h" |
18937 | 35 #include "ass_cache.h" |
36 | |
30200 | 37 static unsigned hashmap_hash(void *buf, size_t len) |
38 { | |
39 return fnv_32a_buf(buf, len, FNV1_32A_INIT); | |
40 } | |
23016 | 41 |
30200 | 42 static int hashmap_key_compare(void *a, void *b, size_t size) |
23016 | 43 { |
30200 | 44 return memcmp(a, b, size) == 0; |
23016 | 45 } |
30200 | 46 |
47 static void hashmap_item_dtor(void *key, size_t key_size, void *value, | |
48 size_t value_size) | |
23016 | 49 { |
30200 | 50 free(key); |
51 free(value); | |
23016 | 52 } |
53 | |
30200 | 54 Hashmap *hashmap_init(ASS_Library *library, size_t key_size, |
55 size_t value_size, int nbuckets, | |
56 HashmapItemDtor item_dtor, | |
57 HashmapKeyCompare key_compare, | |
58 HashmapHash hash) | |
23016 | 59 { |
30200 | 60 Hashmap *map = calloc(1, sizeof(Hashmap)); |
61 map->library = library; | |
62 map->nbuckets = nbuckets; | |
63 map->key_size = key_size; | |
64 map->value_size = value_size; | |
65 map->root = calloc(nbuckets, sizeof(hashmap_item_p)); | |
66 map->item_dtor = item_dtor ? item_dtor : hashmap_item_dtor; | |
67 map->key_compare = key_compare ? key_compare : hashmap_key_compare; | |
68 map->hash = hash ? hash : hashmap_hash; | |
69 return map; | |
23016 | 70 } |
18937 | 71 |
30200 | 72 void hashmap_done(Hashmap *map) |
23016 | 73 { |
30200 | 74 int i; |
75 // print stats | |
76 if (map->count > 0 || map->hit_count + map->miss_count > 0) | |
77 ass_msg(map->library, MSGL_V, | |
78 "cache statistics: \n total accesses: %d\n hits: %d\n " | |
79 "misses: %d\n object count: %d", | |
80 map->hit_count + map->miss_count, map->hit_count, | |
81 map->miss_count, map->count); | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
82 |
30200 | 83 for (i = 0; i < map->nbuckets; ++i) { |
84 HashmapItem *item = map->root[i]; | |
85 while (item) { | |
86 HashmapItem *next = item->next; | |
87 map->item_dtor(item->key, map->key_size, item->value, | |
88 map->value_size); | |
89 free(item); | |
90 item = next; | |
91 } | |
92 } | |
93 free(map->root); | |
94 free(map); | |
23016 | 95 } |
18937 | 96 |
23016 | 97 // does nothing if key already exists |
30200 | 98 void *hashmap_insert(Hashmap *map, void *key, void *value) |
23016 | 99 { |
30200 | 100 unsigned hash = map->hash(key, map->key_size); |
101 HashmapItem **next = map->root + (hash % map->nbuckets); | |
102 while (*next) { | |
103 if (map->key_compare(key, (*next)->key, map->key_size)) | |
104 return (*next)->value; | |
105 next = &((*next)->next); | |
106 assert(next); | |
107 } | |
108 (*next) = malloc(sizeof(HashmapItem)); | |
109 (*next)->key = malloc(map->key_size); | |
110 (*next)->value = malloc(map->value_size); | |
111 memcpy((*next)->key, key, map->key_size); | |
112 memcpy((*next)->value, value, map->value_size); | |
113 (*next)->next = 0; | |
23016 | 114 |
30200 | 115 map->count++; |
116 return (*next)->value; | |
23016 | 117 } |
118 | |
30200 | 119 void *hashmap_find(Hashmap *map, void *key) |
23016 | 120 { |
30200 | 121 unsigned hash = map->hash(key, map->key_size); |
122 HashmapItem *item = map->root[hash % map->nbuckets]; | |
123 while (item) { | |
124 if (map->key_compare(key, item->key, map->key_size)) { | |
125 map->hit_count++; | |
126 return item->value; | |
127 } | |
128 item = item->next; | |
129 } | |
130 map->miss_count++; | |
131 return 0; | |
23016 | 132 } |
133 | |
134 //--------------------------------- | |
135 // font cache | |
136 | |
30200 | 137 static unsigned font_desc_hash(void *buf, size_t len) |
23016 | 138 { |
30200 | 139 ASS_FontDesc *desc = buf; |
140 unsigned hval; | |
141 hval = fnv_32a_str(desc->family, FNV1_32A_INIT); | |
142 hval = fnv_32a_buf(&desc->bold, sizeof(desc->bold), hval); | |
143 hval = fnv_32a_buf(&desc->italic, sizeof(desc->italic), hval); | |
144 return hval; | |
23016 | 145 } |
146 | |
30200 | 147 static int font_compare(void *key1, void *key2, size_t key_size) |
148 { | |
149 ASS_FontDesc *a = key1; | |
150 ASS_FontDesc *b = key2; | |
151 if (strcmp(a->family, b->family) != 0) | |
152 return 0; | |
153 if (a->bold != b->bold) | |
154 return 0; | |
155 if (a->italic != b->italic) | |
156 return 0; | |
157 if (a->treat_family_as_pattern != b->treat_family_as_pattern) | |
158 return 0; | |
31853 | 159 if (a->vertical != b->vertical) |
160 return 0; | |
30200 | 161 return 1; |
18937 | 162 } |
163 | |
30200 | 164 static void font_hash_dtor(void *key, size_t key_size, void *value, |
165 size_t value_size) | |
23016 | 166 { |
30200 | 167 ass_font_free(value); |
168 free(key); | |
23016 | 169 } |
170 | |
30200 | 171 ASS_Font *ass_font_cache_find(Hashmap *font_cache, |
172 ASS_FontDesc *desc) | |
18937 | 173 { |
30200 | 174 return hashmap_find(font_cache, desc); |
21317 | 175 } |
18937 | 176 |
21317 | 177 /** |
178 * \brief Add a face struct to cache. | |
179 * \param font font struct | |
180 */ | |
30200 | 181 void *ass_font_cache_add(Hashmap *font_cache, ASS_Font *font) |
21317 | 182 { |
30200 | 183 return hashmap_insert(font_cache, &(font->desc), font); |
18937 | 184 } |
185 | |
30200 | 186 Hashmap *ass_font_cache_init(ASS_Library *library) |
18937 | 187 { |
30200 | 188 Hashmap *font_cache; |
189 font_cache = hashmap_init(library, sizeof(ASS_FontDesc), | |
190 sizeof(ASS_Font), | |
191 1000, | |
192 font_hash_dtor, font_compare, font_desc_hash); | |
193 return font_cache; | |
18937 | 194 } |
195 | |
30200 | 196 void ass_font_cache_done(Hashmap *font_cache) |
18937 | 197 { |
30200 | 198 hashmap_done(font_cache); |
18937 | 199 } |
200 | |
30200 | 201 |
202 // Create hash/compare functions for bitmap and glyph | |
203 #define CREATE_HASH_FUNCTIONS | |
204 #include "ass_cache_template.h" | |
205 #define CREATE_COMPARISON_FUNCTIONS | |
206 #include "ass_cache_template.h" | |
207 | |
18937 | 208 //--------------------------------- |
23017 | 209 // bitmap cache |
18937 | 210 |
30200 | 211 static void bitmap_hash_dtor(void *key, size_t key_size, void *value, |
212 size_t value_size) | |
23016 | 213 { |
30200 | 214 BitmapHashValue *v = value; |
215 if (v->bm) | |
216 ass_free_bitmap(v->bm); | |
217 if (v->bm_o) | |
218 ass_free_bitmap(v->bm_o); | |
219 if (v->bm_s) | |
220 ass_free_bitmap(v->bm_s); | |
221 free(key); | |
222 free(value); | |
18937 | 223 } |
224 | |
30200 | 225 void *cache_add_bitmap(Hashmap *bitmap_cache, BitmapHashKey *key, |
226 BitmapHashValue *val) | |
18937 | 227 { |
30200 | 228 // Note: this is only an approximation |
229 if (val->bm_o) | |
230 bitmap_cache->cache_size += val->bm_o->w * val->bm_o->h * 3; | |
231 else if (val->bm) | |
232 bitmap_cache->cache_size += val->bm->w * val->bm->h * 3; | |
233 | |
234 return hashmap_insert(bitmap_cache, key, val); | |
18937 | 235 } |
236 | |
237 /** | |
23017 | 238 * \brief Get a bitmap from bitmap cache. |
18937 | 239 * \param key hash key |
240 * \return requested hash val or 0 if not found | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
241 */ |
30200 | 242 BitmapHashValue *cache_find_bitmap(Hashmap *bitmap_cache, |
243 BitmapHashKey *key) | |
18937 | 244 { |
30200 | 245 return hashmap_find(bitmap_cache, key); |
18937 | 246 } |
247 | |
30200 | 248 Hashmap *ass_bitmap_cache_init(ASS_Library *library) |
18937 | 249 { |
30200 | 250 Hashmap *bitmap_cache; |
251 bitmap_cache = hashmap_init(library, | |
252 sizeof(BitmapHashKey), | |
253 sizeof(BitmapHashValue), | |
254 0xFFFF + 13, | |
255 bitmap_hash_dtor, bitmap_compare, | |
256 bitmap_hash); | |
257 return bitmap_cache; | |
18937 | 258 } |
259 | |
30200 | 260 void ass_bitmap_cache_done(Hashmap *bitmap_cache) |
18937 | 261 { |
30200 | 262 hashmap_done(bitmap_cache); |
18937 | 263 } |
264 | |
30200 | 265 Hashmap *ass_bitmap_cache_reset(Hashmap *bitmap_cache) |
19539 | 266 { |
30200 | 267 ASS_Library *lib = bitmap_cache->library; |
268 | |
269 ass_bitmap_cache_done(bitmap_cache); | |
270 return ass_bitmap_cache_init(lib); | |
19539 | 271 } |
272 | |
23018 | 273 //--------------------------------- |
274 // glyph cache | |
275 | |
30200 | 276 static void glyph_hash_dtor(void *key, size_t key_size, void *value, |
277 size_t value_size) | |
23018 | 278 { |
30200 | 279 GlyphHashValue *v = value; |
280 if (v->glyph) | |
281 FT_Done_Glyph(v->glyph); | |
282 if (v->outline_glyph) | |
283 FT_Done_Glyph(v->outline_glyph); | |
284 free(key); | |
285 free(value); | |
23018 | 286 } |
287 | |
30200 | 288 void *cache_add_glyph(Hashmap *glyph_cache, GlyphHashKey *key, |
289 GlyphHashValue *val) | |
23018 | 290 { |
31853 | 291 if (val->glyph && val->glyph->format == FT_GLYPH_FORMAT_BITMAP) { |
292 FT_Bitmap *bitmap = &((FT_BitmapGlyph) val->glyph)->bitmap; | |
293 glyph_cache->cache_size += bitmap->rows * bitmap->pitch; | |
294 } | |
295 | |
30200 | 296 return hashmap_insert(glyph_cache, key, val); |
23018 | 297 } |
298 | |
299 /** | |
300 * \brief Get a glyph from glyph cache. | |
301 * \param key hash key | |
302 * \return requested hash val or 0 if not found | |
29263
0f1b5b68af32
whitespace cosmetics: Remove all trailing whitespace.
diego
parents:
28860
diff
changeset
|
303 */ |
30200 | 304 GlyphHashValue *cache_find_glyph(Hashmap *glyph_cache, |
305 GlyphHashKey *key) | |
23018 | 306 { |
30200 | 307 return hashmap_find(glyph_cache, key); |
23018 | 308 } |
309 | |
30200 | 310 Hashmap *ass_glyph_cache_init(ASS_Library *library) |
23018 | 311 { |
30200 | 312 Hashmap *glyph_cache; |
313 glyph_cache = hashmap_init(library, sizeof(GlyphHashKey), | |
314 sizeof(GlyphHashValue), | |
315 0xFFFF + 13, | |
316 glyph_hash_dtor, glyph_compare, glyph_hash); | |
317 return glyph_cache; | |
23018 | 318 } |
319 | |
30200 | 320 void ass_glyph_cache_done(Hashmap *glyph_cache) |
23018 | 321 { |
30200 | 322 hashmap_done(glyph_cache); |
23018 | 323 } |
324 | |
30200 | 325 Hashmap *ass_glyph_cache_reset(Hashmap *glyph_cache) |
23018 | 326 { |
30200 | 327 ASS_Library *lib = glyph_cache->library; |
328 | |
329 ass_glyph_cache_done(glyph_cache); | |
330 return ass_glyph_cache_init(lib); | |
23018 | 331 } |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
332 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
333 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
334 //--------------------------------- |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
335 // composite cache |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
336 |
30200 | 337 static void composite_hash_dtor(void *key, size_t key_size, void *value, |
338 size_t value_size) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
339 { |
30200 | 340 CompositeHashValue *v = value; |
341 free(v->a); | |
342 free(v->b); | |
343 free(key); | |
344 free(value); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
345 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
346 |
30200 | 347 void *cache_add_composite(Hashmap *composite_cache, |
348 CompositeHashKey *key, | |
349 CompositeHashValue *val) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
350 { |
30200 | 351 return hashmap_insert(composite_cache, key, val); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
352 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
353 |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
354 /** |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
355 * \brief Get a composite bitmap from composite cache. |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
356 * \param key hash key |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
357 * \return requested hash val or 0 if not found |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
358 */ |
30200 | 359 CompositeHashValue *cache_find_composite(Hashmap *composite_cache, |
360 CompositeHashKey *key) | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
361 { |
30200 | 362 return hashmap_find(composite_cache, key); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
363 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
364 |
30200 | 365 Hashmap *ass_composite_cache_init(ASS_Library *library) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
366 { |
30200 | 367 Hashmap *composite_cache; |
368 composite_cache = hashmap_init(library, sizeof(CompositeHashKey), | |
369 sizeof(CompositeHashValue), | |
370 0xFFFF + 13, | |
371 composite_hash_dtor, composite_compare, | |
372 composite_hash); | |
373 return composite_cache; | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
374 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
375 |
30200 | 376 void ass_composite_cache_done(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
377 { |
30200 | 378 hashmap_done(composite_cache); |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
379 } |
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
380 |
30200 | 381 Hashmap *ass_composite_cache_reset(Hashmap *composite_cache) |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
382 { |
30200 | 383 ASS_Library *lib = composite_cache->library; |
384 | |
385 ass_composite_cache_done(composite_cache); | |
386 return ass_composite_cache_init(lib); | |
28789
a0ce88ba2557
Combine adjacent overlapping, translucent glyph borders and shadows to
greg
parents:
26759
diff
changeset
|
387 } |