libbluray | branch: master | hpi1 <[email protected]> | Thu Jun 20 15:02:33 2013 +0300| [656d5b97da6a0aaa8c9795776080acd75b1157d6] | committer: hpi1
Reference-counted RLE images > http://git.videolan.org/gitweb.cgi/libbluray.git/?a=commit;h=656d5b97da6a0aaa8c9795776080acd75b1157d6 --- src/Makefile.am | 2 + src/libbluray/decoders/overlay.h | 37 +++++++++++- src/libbluray/decoders/pg_decode.c | 11 +++- src/util/macro.h | 1 + src/util/refcnt.c | 112 ++++++++++++++++++++++++++++++++++++ src/util/refcnt.h | 52 +++++++++++++++++ 6 files changed, 211 insertions(+), 4 deletions(-) diff --git a/src/Makefile.am b/src/Makefile.am index 02a1a9f..30b8a63 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -72,6 +72,8 @@ libbluray_la_SOURCES = \ file/filesystem.h \ file/filesystem.c \ util/attributes.h \ + util/refcnt.h \ + util/refcnt.c \ util/strutl.c \ util/strutl.h \ util/macro.h \ diff --git a/src/libbluray/decoders/overlay.h b/src/libbluray/decoders/overlay.h index 9f53dd8..96dd958 100644 --- a/src/libbluray/decoders/overlay.h +++ b/src/libbluray/decoders/overlay.h @@ -81,10 +81,45 @@ typedef struct bd_overlay_s { uint16_t crop_h; uint8_t palette_update_flag; /* only palette was changed */ - } BD_OVERLAY; /* + RLE images are reference-counted. If application caches rle data for later use, + it needs to use bd_refcnt_inc() and bd_refcnt_dec(). +*/ + +void bd_refcnt_inc(const void *); +void bd_refcnt_dec(const void *); + +#if 0 +BD_OVERLAY *bd_overlay_copy(const BD_OVERLAY *src) +{ + BD_OVERLAY *ov = malloc(sizeof(*ov)); + memcpy(ov, src, sizeof(*ov)); + if (ov->palette) { + ov->palette = malloc(256 * sizeof(BD_PG_PALETTE_ENTRY)); + memcpy((void*)ov->palette, src->palette, 256 * sizeof(BD_PG_PALETTE_ENTRY)); + } + if (ov->img) { + bd_refcnt_inc(ov->img); + } + return ov; +} + +void bd_overlay_free(BD_OVERLAY **pov) +{ + if (pov && *pov) { + BD_OVERLAY *ov = *pov; + void *p = (void*)ov->palette; + bd_refcnt_dec(ov->img); + X_FREE(p); + ov->palette = NULL; + X_FREE(*pov); + } +} +#endif + +/* * ARGB overlays */ diff --git a/src/libbluray/decoders/pg_decode.c b/src/libbluray/decoders/pg_decode.c index fca647d..cd9a30f 100644 --- a/src/libbluray/decoders/pg_decode.c +++ b/src/libbluray/decoders/pg_decode.c @@ -22,10 +22,14 @@ #include "util/macro.h" #include "util/logging.h" #include "util/bits.h" +#include "util/refcnt.h" #include <string.h> #include <stdlib.h> +/* + * + */ void pg_decode_video_descriptor(BITBUFFER *bb, BD_PG_VIDEO_DESCRIPTOR *p) { @@ -120,7 +124,7 @@ static int _decode_rle(BITBUFFER *bb, BD_PG_OBJECT *p) if (rle_size < 1) rle_size = 1; - p->img = realloc(p->img, rle_size * sizeof(BD_PG_RLE_ELEM)); + p->img = refcnt_realloc(p->img, rle_size * sizeof(BD_PG_RLE_ELEM)); if (!p->img) { BD_DEBUG(DBG_DECODE | DBG_CRIT, "pg_decode_object(): relloc(%zu) failed\n", rle_size * sizeof(BD_PG_RLE_ELEM)); @@ -162,7 +166,7 @@ static int _decode_rle(BITBUFFER *bb, BD_PG_OBJECT *p) if (num_rle >= rle_size) { void *tmp = p->img; rle_size *= 2; - p->img = realloc(p->img, rle_size * sizeof(BD_PG_RLE_ELEM)); + p->img = refcnt_realloc(p->img, rle_size * sizeof(BD_PG_RLE_ELEM)); if (!p->img) { BD_DEBUG(DBG_DECODE | DBG_CRIT, "pg_decode_object(): relloc(%zu) failed\n", rle_size * sizeof(BD_PG_RLE_ELEM)); @@ -260,7 +264,8 @@ int pg_decode_windows(BITBUFFER *bb, BD_PG_WINDOWS *p) void pg_clean_object(BD_PG_OBJECT *p) { if (p) { - X_FREE(p->img); + bd_refcnt_dec(p->img); + p->img = NULL; } } diff --git a/src/util/macro.h b/src/util/macro.h index b643448..60c5c68 100644 --- a/src/util/macro.h +++ b/src/util/macro.h @@ -65,6 +65,7 @@ auto_cast_wrapper<R> auto_cast(const R& x) # define calloc(n,s) auto_cast(calloc(n,s)) # define malloc(s) auto_cast(malloc(s)) # define realloc(p,s) auto_cast(realloc(p,s)) +# define refcnt_realloc(p,s) auto_cast(refcnt_realloc(p,s)) #endif /* __cplusplus */ diff --git a/src/util/refcnt.c b/src/util/refcnt.c new file mode 100644 index 0000000..d78a299 --- /dev/null +++ b/src/util/refcnt.c @@ -0,0 +1,112 @@ +/* + * This file is part of libbluray + * Copyright (C) 2013 Petri Hintukainen <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include "refcnt.h" + +#include "logging.h" +#include "macro.h" +#include "mutex.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +/* + * + */ + +typedef struct { + BD_MUTEX mutex; /* initialized only if counted == 1 */ + int count; /* reference count */ + unsigned counted; /* 1 if this object is ref-counted */ +} BD_REFCNT; + +/* + * + */ + +void bd_refcnt_inc(const void *obj) +{ + if (!obj) { + return; + } + + BD_REFCNT *ref = &(((BD_REFCNT *)(intptr_t)obj)[-1]); + + if (!ref->counted) { + bd_mutex_init(&ref->mutex); + ref->counted = 1; + ref->count = 2; + return; + } + + bd_mutex_lock(&ref->mutex); + ++ref->count; + bd_mutex_unlock(&ref->mutex); +} + +void bd_refcnt_dec(const void *obj) +{ + if (!obj) { + return; + } + + BD_REFCNT *ref = &((BD_REFCNT *)(intptr_t)obj)[-1]; + + if (ref->counted) { + int count; + + bd_mutex_lock(&ref->mutex); + count = --ref->count; + bd_mutex_unlock(&ref->mutex); + + if (count > 0) { + return; + } + + bd_mutex_destroy(&ref->mutex); + } + + X_FREE(ref); +} + +void *refcnt_realloc(void *obj, size_t sz) +{ + sz += sizeof(BD_REFCNT); + + if (obj) { + if (((BD_REFCNT *)obj)[-1].counted) { + bd_refcnt_dec(obj); + BD_DEBUG(DBG_CRIT, "refcnt_realloc(): realloc locked object !\n"); + obj = NULL; + } + } + + if (obj) { + obj = realloc(&((BD_REFCNT *)obj)[-1], sz); + } else { + obj = realloc(NULL, sz); + memset(obj, 0, sizeof(BD_REFCNT)); + } + + return &((BD_REFCNT *)obj)[1]; +} + + + diff --git a/src/util/refcnt.h b/src/util/refcnt.h new file mode 100644 index 0000000..421ab5c --- /dev/null +++ b/src/util/refcnt.h @@ -0,0 +1,52 @@ +/* + * This file is part of libbluray + * Copyright (C) 2013 Petri Hintukainen <[email protected]> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef BD_REFCNT_H_ +#define BD_FEFCNT_H_ + +#include "attributes.h" + +#include <sys/types.h> + +/* + * Reference-counted memory blocks. + * + * - Object must be allocated with refcnt_realloc(NULL, size). + * Returned object has reference count of 1. + * - Object can be re-allocated with refcnt_realloc(obj, size) + * as long as bd_refcnt_inc() has not been called. + * - Object must be freed with bd_refcnt_dec(). + * + * by default, reference counting is not used (use count = 1). + * Reference counting is initialized during first call to bd_refcnt_inc(). + * This results in reference count = 2. + * + * This is thread-safe as long as first bd_refcnt_inc() is done from the + * same thread that owns the object initially. + * + */ + +BD_PRIVATE void *refcnt_realloc(void *obj, size_t sz); + +#ifndef BD_OVERLAY_INTERFACE_VERSION +void bd_refcnt_inc(const void *obj); +void bd_refcnt_dec(const void *obj); +#endif + +#endif // BD_REFCNT_H_ _______________________________________________ libbluray-devel mailing list [email protected] http://mailman.videolan.org/listinfo/libbluray-devel
