Mercurial > mplayer.hg
annotate libass/ass_cache.c @ 32737:ce0b4f3bb12d
Continue playing even if we reached video EOF if there is still audio
data to play.
Fixes playback of http://samples.mplayerhq.hu/mov/audio_with_still.m4a
author | reimar |
---|---|
date | Thu, 27 Jan 2011 20:39:01 +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 } |