[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