shithub: dav1d

Download patch

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);