picture: add per plane reference counting

Signed-off-by: James Almer <jamrial@gmail.com>
This commit is contained in:
James Almer
2023-02-25 22:33:46 +00:00
parent aa15e3ea74
commit 92d8b81542
+46 -6
View File
@@ -87,19 +87,33 @@ void dav1d_default_picture_release(Dav1dPicture *const p, void *const cookie) {
}
struct pic_ctx_context {
struct Dav1dRef *plane_ref[3]; /* MUST BE FIRST */
enum Dav1dPixelLayout layout;
void *extra_ptr; /* MUST BE AT THE END */
};
struct plane_ctx_context {
Dav1dPicAllocator allocator;
Dav1dPicture pic;
void *extra_ptr; /* MUST BE AT THE END */
};
static void free_buffer(const uint8_t *const data, void *const user_data) {
struct pic_ctx_context *pic_ctx = user_data;
const int planes = pic_ctx->layout != DAV1D_PIXEL_LAYOUT_I400 ? 3 : 1;
pic_ctx->allocator.release_picture_callback(&pic_ctx->pic,
pic_ctx->allocator.cookie);
for (int i = 0; i < planes; i++)
dav1d_ref_dec(&pic_ctx->plane_ref[i]);
free(pic_ctx);
}
static void free_plane_buffer(const uint8_t *const data, void *const user_data) {
struct plane_ctx_context *plane_ctx = user_data;
plane_ctx->allocator.release_picture_callback(&plane_ctx->pic,
plane_ctx->allocator.cookie);
free(plane_ctx);
}
static int picture_alloc_with_edges(Dav1dContext *const c,
Dav1dPicture *const p,
const int w, const int h,
@@ -122,6 +136,7 @@ static int picture_alloc_with_edges(Dav1dContext *const c,
struct pic_ctx_context *pic_ctx = malloc(extra + sizeof(struct pic_ctx_context));
if (pic_ctx == NULL)
return DAV1D_ERR(ENOMEM);
memset(pic_ctx, 0, sizeof(struct pic_ctx_context));
p->p.w = w;
p->p.h = h;
@@ -139,8 +154,7 @@ static int picture_alloc_with_edges(Dav1dContext *const c,
return res;
}
pic_ctx->allocator = *p_allocator;
pic_ctx->pic = *p;
pic_ctx->layout = p->p.layout;
if (!(p->ref = dav1d_ref_wrap(p->data[0], free_buffer, pic_ctx))) {
p_allocator->release_picture_callback(p, p_allocator->cookie);
@@ -149,6 +163,31 @@ static int picture_alloc_with_edges(Dav1dContext *const c,
return DAV1D_ERR(ENOMEM);
}
struct plane_ctx_context *plane_ctx = malloc(sizeof(struct plane_ctx_context));
if (plane_ctx == NULL){
dav1d_ref_dec(&p->ref);
p_allocator->release_picture_callback(p, p_allocator->cookie);
return DAV1D_ERR(ENOMEM);
}
plane_ctx->allocator = *p_allocator;
plane_ctx->pic = *p;
pic_ctx->plane_ref[0] = dav1d_ref_wrap(p->data[0], free_plane_buffer, plane_ctx);
if (!pic_ctx->plane_ref[0]) {
dav1d_ref_dec(&p->ref);
p_allocator->release_picture_callback(p, p_allocator->cookie);
free(plane_ctx);
dav1d_log(c, "Failed to wrap picture plane: %s\n", strerror(errno));
return DAV1D_ERR(ENOMEM);
}
const int planes = p->p.layout != DAV1D_PIXEL_LAYOUT_I400 ? 3 : 1;
for (int i = 1; i < planes; i++) {
pic_ctx->plane_ref[i] = pic_ctx->plane_ref[0];
dav1d_ref_inc(pic_ctx->plane_ref[i]);
}
p->seq_hdr_ref = seq_hdr_ref;
if (seq_hdr_ref) dav1d_ref_inc(seq_hdr_ref);
@@ -214,13 +253,14 @@ int dav1d_picture_alloc_copy(Dav1dContext *const c, Dav1dPicture *const dst, con
const Dav1dPicture *const src)
{
struct pic_ctx_context *const pic_ctx = src->ref->user_data;
struct plane_ctx_context *const plane_ctx = pic_ctx->plane_ref[0]->user_data;
const int res = picture_alloc_with_edges(c, dst, w, src->p.h,
src->seq_hdr, src->seq_hdr_ref,
src->frame_hdr, src->frame_hdr_ref,
src->content_light, src->content_light_ref,
src->mastering_display, src->mastering_display_ref,
src->itut_t35, src->itut_t35_ref,
src->p.bpc, &src->m, &pic_ctx->allocator,
src->p.bpc, &src->m, &plane_ctx->allocator,
0, NULL);
return res;
}