[libbluray-devel] Reference-counted RLE images
hpi1
git at videolan.org
Thu Jun 20 14:13:03 CEST 2013
libbluray | branch: master | hpi1 <hpi1 at anonymous.org> | 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 <phintuka at users.sourceforge.net>
+ *
+ * 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 <phintuka at users.sourceforge.net>
+ *
+ * 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_
More information about the libbluray-devel
mailing list