ref: f53749e12241e6d61d9d2bd51666302c59962fc9
parent: f4e88f25f56f5c3ae6650d4c42afc265428f0459
author: Ronald S. Bultje <rsbultje@gmail.com>
date: Fri Sep 28 09:27:07 EDT 2018
Wrappable data structure
--- a/include/dav1d/data.h
+++ b/include/dav1d/data.h
@@ -45,6 +45,18 @@
DAV1D_API int dav1d_data_create(Dav1dData *data, size_t sz);
/**
+ * Wrap an existing data packet.
+ * $ptr/$sz are the pointer and size of the data to be wrapped.
+ * $free_callback/$user_data are a function and function argument to be
+ * called when we release our last reference to this data. In this callback,
+ * $data will be the $ptr argument to this function, and $user_data will be
+ * the $user_data input argument to this function.
+ */
+DAV1D_API int dav1d_data_wrap(Dav1dData *data, uint8_t *ptr, size_t sz,
+ void (*free_callback)(uint8_t *data, void *user_data),
+ void *user_data);
+
+/**
* Free data.
*/
DAV1D_API void dav1d_data_unref(Dav1dData *buf);
--- a/src/data.c
+++ b/src/data.c
@@ -48,6 +48,22 @@
return 0;
}
+int dav1d_data_wrap(Dav1dData *const buf, uint8_t *const ptr, const size_t sz,
+ void (*free_callback)(uint8_t *data, void *user_data),
+ void *user_data)
+{
+ validate_input_or_ret(buf != NULL, -EINVAL);
+ validate_input_or_ret(ptr != NULL, -EINVAL);
+ validate_input_or_ret(free_callback != NULL, -EINVAL);
+
+ buf->ref = dav1d_ref_wrap(ptr, sz, free_callback, user_data);
+ if (!buf->ref) return -ENOMEM;
+ buf->data = ptr;
+ buf->sz = sz;
+
+ return 0;
+}
+
void dav1d_data_unref(Dav1dData *const buf) {
dav1d_ref_dec(buf->ref);
memset(buf, 0, sizeof(*buf));
--- a/src/ref.c
+++ b/src/ref.c
@@ -31,6 +31,10 @@
#include "src/ref.h"
+static void default_free_callback(uint8_t *const data, void *const user_data) {
+ dav1d_free_aligned(data);
+}
+
Dav1dRef *dav1d_ref_create(const size_t size) {
Dav1dRef *res = malloc(sizeof(Dav1dRef));
void *data = dav1d_alloc_aligned(size, 32);
@@ -44,10 +48,27 @@
res->size = size;
atomic_init(&res->ref_cnt, 1);
res->data = data;
+ res->free_callback = default_free_callback;
return res;
}
+Dav1dRef *dav1d_ref_wrap(uint8_t *const ptr, const size_t sz,
+ void (*free_callback)(uint8_t *data, void *user_data),
+ void *user_data)
+{
+ Dav1dRef *res = malloc(sizeof(Dav1dRef));
+ if (!res) return NULL;
+
+ res->data = ptr;
+ res->size = sz;
+ atomic_init(&res->ref_cnt, 1);
+ res->free_callback = free_callback;
+ res->user_data = user_data;
+
+ return res;
+}
+
void dav1d_ref_inc(Dav1dRef *const ref) {
atomic_fetch_add(&ref->ref_cnt, 1);
}
@@ -54,7 +75,7 @@
void dav1d_ref_dec(Dav1dRef *const ref) {
if (atomic_fetch_sub(&ref->ref_cnt, 1) == 1) {
- dav1d_free_aligned(ref->data);
+ ref->free_callback(ref->data, ref->user_data);
free(ref);
}
}
--- a/src/ref.h
+++ b/src/ref.h
@@ -37,9 +37,14 @@
void *data;
size_t size;
atomic_int ref_cnt;
+ void (*free_callback)(uint8_t *data, void *user_data);
+ void *user_data;
};
Dav1dRef *dav1d_ref_create(size_t size);
+Dav1dRef *dav1d_ref_wrap(uint8_t *ptr, size_t sz,
+ void (*free_callback)(uint8_t *data, void *user_data),
+ void *user_data);
void dav1d_ref_inc(Dav1dRef *ref);
void dav1d_ref_dec(Dav1dRef *ref);