Commit c7007c92 authored by Michael Bradshaw's avatar Michael Bradshaw

Add a user data pointer to Dav1dDataProps

parent 9ea56386
......@@ -43,6 +43,14 @@
#endif
#endif
/**
* A reference-counted object wrapper for a user-configurable pointer.
*/
typedef struct Dav1dUserData {
const uint8_t *data; ///< data pointer
struct Dav1dRef *ref; ///< allocation origin
} Dav1dUserData;
/**
* Input packet metadata which are copied from the input data used to
* decode each image into the matching structure of the output image
......@@ -56,6 +64,7 @@ typedef struct Dav1dDataProps {
int64_t duration; ///< container duration of input data, 0 if unknown (default)
int64_t offset; ///< stream offset of input data, -1 if unknown (default)
size_t size; ///< packet size, default Dav1dData.sz
struct Dav1dUserData user_data; ///< user-configurable data, default NULL members
} Dav1dDataProps;
#endif // __DAV1D_COMMON_H__
......@@ -58,19 +58,50 @@ DAV1D_API uint8_t * dav1d_data_create(Dav1dData *data, size_t sz);
* @param sz Size of the data.
* @param free_callback Function to be called when we release our last
* reference to this data. In this callback, $buf will be
* the $buf argument to this function, and $user_data
* will be the $user_data input argument to this function.
* @param user_data Opaque parameter passed to free_callback().
* the $buf argument to this function, and $cookie will
* be the $cookie input argument to this function.
* @param cookie Opaque parameter passed to free_callback().
*
* @return 0 on success. A negative errno value on error.
*/
DAV1D_API int dav1d_data_wrap(Dav1dData *data, const uint8_t *buf, size_t sz,
void (*free_callback)(const uint8_t *buf, void *user_data),
void *user_data);
void (*free_callback)(const uint8_t *buf, void *cookie),
void *cookie);
/**
* Wrap a user-provided data pointer into a reference counted object.
*
* data->m.user_data field will initialized to wrap the provided $user_data
* pointer.
*
* $free_callback will be called on the same thread that released the last
* reference. If frame threading is used, make sure $free_callback is
* thread-safe.
*
* @param data Input context.
* @param user_data The user data to be wrapped.
* @param free_callback Function to be called when we release our last
* reference to this data. In this callback, $user_data
* will be the $user_data argument to this function, and
* $cookie will be the $cookie input argument to this
* function.
* @param cookie Opaque parameter passed to $free_callback.
*
* @return 0 on success. A negative errno value on error.
*/
DAV1D_API int dav1d_data_wrap_user_data(Dav1dData *data,
const uint8_t *user_data,
void (*free_callback)(const uint8_t *user_data,
void *cookie),
void *cookie);
/**
* Free the data reference.
*
* The reference count for data->m.user_data will be decremented (if it has been
* initialized with dav1d_data_wrap_user_data). The $data object will be memset
* to 0.
*
* @param data Input context.
*/
DAV1D_API void dav1d_data_unref(Dav1dData *data);
......
......@@ -27,6 +27,7 @@
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
......@@ -49,6 +50,8 @@ uint8_t *dav1d_data_create_internal(Dav1dData *const buf, const size_t sz) {
buf->m.timestamp = INT64_MIN;
buf->m.duration = 0;
buf->m.offset = -1;
buf->m.user_data.data = NULL;
buf->m.user_data.ref = NULL;
return buf->ref->data;
}
......@@ -56,20 +59,38 @@ uint8_t *dav1d_data_create_internal(Dav1dData *const buf, const size_t sz) {
int dav1d_data_wrap_internal(Dav1dData *const buf, const uint8_t *const ptr,
const size_t sz,
void (*const free_callback)(const uint8_t *data,
void *user_data),
void *const user_data)
void *cookie),
void *const cookie)
{
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, free_callback, user_data);
buf->ref = dav1d_ref_wrap(ptr, free_callback, cookie);
if (!buf->ref) return -ENOMEM;
buf->data = ptr;
buf->sz = buf->m.size = sz;
buf->m.timestamp = INT64_MIN;
buf->m.duration = 0;
buf->m.offset = -1;
buf->m.user_data.data = NULL;
buf->m.user_data.ref = NULL;
return 0;
}
int dav1d_data_wrap_user_data_internal(Dav1dData *const buf,
const uint8_t *const user_data,
void (*const free_callback)(const uint8_t *user_data,
void *cookie),
void *const cookie)
{
validate_input_or_ret(buf != NULL, -EINVAL);
validate_input_or_ret(free_callback != NULL, -EINVAL);
buf->m.user_data.ref = dav1d_ref_wrap(user_data, free_callback, cookie);
if (!buf->m.user_data.ref) return -ENOMEM;
buf->m.user_data.data = user_data;
return 0;
}
......@@ -86,12 +107,24 @@ void dav1d_data_move_ref(Dav1dData *const dst, Dav1dData *const src) {
memset(src, 0, sizeof(*src));
}
void dav1d_data_props_copy(Dav1dDataProps *const dst,
const Dav1dDataProps *const src)
{
assert(dst != NULL);
assert(src != NULL);
*dst = *src;
if (dst->user_data.ref) dav1d_ref_inc(dst->user_data.ref);
}
void dav1d_data_unref_internal(Dav1dData *const buf) {
validate_input(buf != NULL);
struct Dav1dRef *user_data_ref = buf->m.user_data.ref;
if (buf->ref) {
validate_input(buf->data != NULL);
dav1d_ref_dec(&buf->ref);
}
memset(buf, 0, sizeof(*buf));
dav1d_ref_dec(&user_data_ref);
}
......@@ -35,11 +35,22 @@
*/
void dav1d_data_move_ref(Dav1dData *dst, Dav1dData *src);
/**
* Copy the source properties to the destitionatin and increase the
* user_data's reference count (if it's not NULL).
*/
void dav1d_data_props_copy(Dav1dDataProps *dst, const Dav1dDataProps *src);
uint8_t *dav1d_data_create_internal(Dav1dData *buf, size_t sz);
int dav1d_data_wrap_internal(Dav1dData *buf, const uint8_t *ptr, size_t sz,
void (*free_callback)(const uint8_t *data,
void *user_data),
void *user_data);
int dav1d_data_wrap_user_data_internal(Dav1dData *buf,
const uint8_t *user_data,
void (*free_callback)(const uint8_t *user_data,
void *cookie),
void *cookie);
void dav1d_data_unref_internal(Dav1dData *buf);
#endif /* __DAV1D_SRC_DATA_H__ */
......@@ -3185,7 +3185,7 @@ int dav1d_submit_frame(Dav1dContext *const c) {
f->frame_hdr->show_frame, &c->allocator);
if (res < 0) goto error;
f->sr_cur.p.m = f->tile[0].data.m;
dav1d_data_props_copy(&f->sr_cur.p.m, &f->tile[0].data.m);
f->sr_cur.p.frame_hdr = f->frame_hdr;
f->sr_cur.p.frame_hdr_ref = f->frame_hdr_ref;
dav1d_ref_inc(f->frame_hdr_ref);
......
......@@ -521,6 +521,18 @@ int dav1d_data_wrap(Dav1dData *const buf, const uint8_t *const ptr,
return dav1d_data_wrap_internal(buf, ptr, sz, free_callback, user_data);
}
int dav1d_data_wrap_user_data(Dav1dData *const buf,
const uint8_t *const user_data,
void (*const free_callback)(const uint8_t *user_data,
void *cookie),
void *const cookie)
{
return dav1d_data_wrap_user_data_internal(buf,
user_data,
free_callback,
cookie);
}
void dav1d_data_unref(Dav1dData *const buf) {
dav1d_data_unref_internal(buf);
}
......@@ -1325,7 +1325,7 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in, int global) {
assert(pkt_bytelen >= (bit_pos >> 3));
dav1d_ref_inc(in->ref);
c->tile[c->n_tile_data].data.ref = in->ref;
c->tile[c->n_tile_data].data.m = in->m;
dav1d_data_props_copy(&c->tile[c->n_tile_data].data.m, &in->m);
c->tile[c->n_tile_data].data.data = in->data + (bit_pos >> 3);
c->tile[c->n_tile_data].data.sz = pkt_bytelen - (bit_pos >> 3);
// ensure tile groups are in order and sane, see 6.10.1
......@@ -1359,7 +1359,7 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in, int global) {
if (c->n_fc == 1) {
dav1d_picture_ref(&c->out,
&c->refs[c->frame_hdr->existing_frame_idx].p.p);
c->out.m = in->m;
dav1d_data_props_copy(&c->out.m, &in->m);
} else {
// need to append this to the frame output queue
const unsigned next = c->frame_thread.next++;
......@@ -1383,7 +1383,7 @@ int dav1d_parse_obus(Dav1dContext *const c, Dav1dData *const in, int global) {
dav1d_thread_picture_ref(out_delayed,
&c->refs[c->frame_hdr->existing_frame_idx].p);
out_delayed->visible = 1;
out_delayed->p.m = in->m;
dav1d_data_props_copy(&out_delayed->p.m, &in->m);
pthread_mutex_unlock(&f->frame_thread.td.lock);
}
if (c->refs[c->frame_hdr->existing_frame_idx].p.p.frame_hdr->frame_type == DAV1D_FRAME_TYPE_KEY) {
......
......@@ -92,8 +92,10 @@ struct pic_ctx_context {
static void free_buffer(const uint8_t *const data, void *const user_data) {
struct pic_ctx_context *pic_ctx = user_data;
struct Dav1dRef *user_data_ref = pic_ctx->pic.m.user_data.ref;
pic_ctx->allocator.release_picture_callback(&pic_ctx->pic,
pic_ctx->allocator.cookie);
if (user_data_ref) dav1d_ref_dec(&user_data_ref);
free(pic_ctx);
}
......@@ -120,6 +122,8 @@ static int picture_alloc_with_edges(Dav1dPicture *const p,
p->m.timestamp = INT64_MIN;
p->m.duration = 0;
p->m.offset = -1;
p->m.user_data.data = NULL;
p->m.user_data.ref = NULL;
p->p.layout = layout;
p->p.bpc = bpc;
int res = p_allocator->alloc_picture_callback(p, p_allocator->cookie);
......@@ -176,7 +180,7 @@ int dav1d_picture_alloc_copy(Dav1dPicture *const dst, const int w,
if (!res) {
dst->p = src->p;
dst->m = src->m;
dav1d_data_props_copy(&dst->m, &src->m);
dst->p.w = w;
dst->frame_hdr = src->frame_hdr;
dst->frame_hdr_ref = src->frame_hdr_ref;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment