diff options
author | John Stebbins <[email protected]> | 2017-05-31 10:21:53 -0700 |
---|---|---|
committer | Bradley Sepos <[email protected]> | 2017-06-06 11:42:09 -0400 |
commit | 021b3caa6efbfadb212bb1e686c2de08da6df2c6 (patch) | |
tree | 5b972504671f6bb1c19f99ad36a477f50dbe7cba /libhb/unsharp.c | |
parent | c365e557920c8911e638534b5fa5cc59487834a7 (diff) |
filter: add frame parallelizing filter wrapper
This wrapper can be used to frame parallelize simple video filters. By
simple, I mean there can be no temporal context that is shared from one
frame to the next.
Wrap unsharp and lapsharp filters. unsharp required a small rework to
separate out temporary storage that is required when processing each
frame. We now need to duplicate this storage for each thread.
Closes #759.
Diffstat (limited to 'libhb/unsharp.c')
-rw-r--r-- | libhb/unsharp.c | 169 |
1 files changed, 121 insertions, 48 deletions
diff --git a/libhb/unsharp.c b/libhb/unsharp.c index 2d5a1d577..8f1c99e6b 100644 --- a/libhb/unsharp.c +++ b/libhb/unsharp.c @@ -19,6 +19,8 @@ typedef struct { + int pix_fmt; // source pixel format + int width; // source video width double strength; // strength int size; // pixel context region width (must be odd) @@ -26,24 +28,37 @@ typedef struct int amount; int scalebits; int32_t halfscale; - uint32_t * SC[UNSHARP_SIZE_MAX - 1]; } unsharp_plane_context_t; +typedef struct +{ + uint32_t * SC[UNSHARP_SIZE_MAX - 1]; +} unsharp_thread_context_t; + +typedef unsharp_thread_context_t unsharp_thread_context3_t[3]; + struct hb_filter_private_s { - unsharp_plane_context_t plane_ctx[3]; + unsharp_plane_context_t plane_ctx[3]; + unsharp_thread_context3_t * thread_ctx; + int threads; }; -static int hb_unsharp_init(hb_filter_object_t *filter, - hb_filter_init_t *init); +static int unsharp_init(hb_filter_object_t *filter, + hb_filter_init_t *init); + +static int unsharp_init_thread(hb_filter_object_t *filter, int threads); -static int hb_unsharp_work(hb_filter_object_t *filter, - hb_buffer_t ** buf_in, - hb_buffer_t ** buf_out); +static int unsharp_work(hb_filter_object_t *filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out); +static int unsharp_work_thread(hb_filter_object_t *filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out, int thread); -static void hb_unsharp_close(hb_filter_object_t *filter); +static void unsharp_close(hb_filter_object_t *filter); -static const char hb_unsharp_template[] = +static const char unsharp_template[] = "y-strength=^"HB_FLOAT_REG"$:y-size=^"HB_INT_REG"$:" "cb-strength=^"HB_FLOAT_REG"$:cb-size=^"HB_INT_REG"$:" "cr-strength=^"HB_FLOAT_REG"$:cr-size=^"HB_INT_REG"$"; @@ -54,20 +69,23 @@ hb_filter_object_t hb_filter_unsharp = .enforce_order = 1, .name = "Sharpen (unsharp)", .settings = NULL, - .init = hb_unsharp_init, - .work = hb_unsharp_work, - .close = hb_unsharp_close, - .settings_template = hb_unsharp_template, + .init = unsharp_init, + .init_thread = unsharp_init_thread, + .work = unsharp_work, + .work_thread = unsharp_work_thread, + .close = unsharp_close, + .settings_template = unsharp_template, }; -static void hb_unsharp(const uint8_t *src, - uint8_t *dst, - const int width, - const int height, - const int stride, - unsharp_plane_context_t * ctx) +static void unsharp(const uint8_t *src, + uint8_t *dst, + const int width, + const int height, + const int stride, + unsharp_plane_context_t * ctx, + unsharp_thread_context_t * tctx) { - uint32_t **SC = ctx->SC; + uint32_t **SC = tctx->SC; uint32_t SR[UNSHARP_SIZE_MAX - 1], Tmp1, Tmp2; @@ -138,10 +156,15 @@ static void hb_unsharp(const uint8_t *src, } } -static int hb_unsharp_init(hb_filter_object_t *filter, - hb_filter_init_t *init) +static int unsharp_init(hb_filter_object_t *filter, + hb_filter_init_t *init) { filter->private_data = calloc(sizeof(struct hb_filter_private_s), 1); + if (filter->private_data == NULL) + { + hb_error("Unsharp calloc failed"); + return -1; + } hb_filter_private_t * pv = filter->private_data; // Mark parameters unset @@ -179,7 +202,8 @@ static int hb_unsharp_init(hb_filter_object_t *filter, for (int c = 0; c < 3; c++) { unsharp_plane_context_t * ctx = &pv->plane_ctx[c]; - int w = hb_image_width(init->pix_fmt, init->geometry.width, c); + + ctx->width = init->geometry.width; // Replace unset values with defaults if (ctx->strength == -1) @@ -204,44 +228,85 @@ static int hb_unsharp_init(hb_filter_object_t *filter, ctx->steps = ctx->size / 2; ctx->scalebits = ctx->steps * 4; ctx->halfscale = 1 << (ctx->scalebits - 1); + } - int z; - for (z = 0; z < 2 * ctx->steps; z++) - { - ctx->SC[z] = malloc(sizeof(*(ctx->SC[z])) * (w + 2 * ctx->steps)); - } + if (unsharp_init_thread(filter, 1) < 0) + { + unsharp_close(filter); + return -1; } return 0; } -static void hb_unsharp_close(hb_filter_object_t * filter) +static void unsharp_thread_close(hb_filter_private_t *pv) { - hb_filter_private_t *pv = filter->private_data; - - if (pv == NULL) + int c, z; + for (c = 0; c < 3; c++) { - return; + unsharp_plane_context_t * ctx = &pv->plane_ctx[c]; + for (int t = 0; t < pv->threads; t++) + { + unsharp_thread_context_t * tctx = &pv->thread_ctx[t][c]; + for (z = 0; z < 2 * ctx->steps; z++) + { + free(tctx->SC[z]); + tctx->SC[z] = NULL; + } + } } + free(pv->thread_ctx); +} - int c, z; - for (c = 0; c < 3; c++) +static int unsharp_init_thread(hb_filter_object_t *filter, int threads) +{ + hb_filter_private_t * pv = filter->private_data; + + unsharp_thread_close(pv); + pv->thread_ctx = calloc(threads, sizeof(unsharp_thread_context3_t)); + pv->threads = threads; + for (int c = 0; c < 3; c++) { unsharp_plane_context_t * ctx = &pv->plane_ctx[c]; - for (z = 0; z < ctx->steps; z++) + int w = hb_image_width(ctx->pix_fmt, ctx->width, c); + + for (int t = 0; t < threads; t++) { - free(ctx->SC[z]); - ctx->SC[z] = NULL; + unsharp_thread_context_t * tctx = &pv->thread_ctx[t][c]; + int z; + for (z = 0; z < 2 * ctx->steps; z++) + { + tctx->SC[z] = malloc(sizeof(*(tctx->SC[z])) * + (w + 2 * ctx->steps)); + if (tctx->SC[z] == NULL) + { + hb_error("Unsharp calloc failed"); + unsharp_close(filter); + return -1; + } + } } } + return 0; +} + +static void unsharp_close(hb_filter_object_t * filter) +{ + hb_filter_private_t *pv = filter->private_data; + + if (pv == NULL) + { + return; + } + unsharp_thread_close(pv); free(pv); filter->private_data = NULL; } -static int hb_unsharp_work(hb_filter_object_t *filter, - hb_buffer_t ** buf_in, - hb_buffer_t ** buf_out) +static int unsharp_work_thread(hb_filter_object_t *filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out, int thread) { hb_filter_private_t *pv = filter->private_data; hb_buffer_t *in = *buf_in, *out; @@ -258,13 +323,14 @@ static int hb_unsharp_work(hb_filter_object_t *filter, int c; for (c = 0; c < 3; c++) { - unsharp_plane_context_t * ctx = &pv->plane_ctx[c]; - hb_unsharp(in->plane[c].data, - out->plane[c].data, - in->plane[c].width, - in->plane[c].height, - in->plane[c].stride, - ctx); + unsharp_plane_context_t * ctx = &pv->plane_ctx[c]; + unsharp_thread_context_t * tctx = &pv->thread_ctx[thread][c]; + unsharp(in->plane[c].data, + out->plane[c].data, + in->plane[c].width, + in->plane[c].height, + in->plane[c].stride, + ctx, tctx); } out->s = in->s; @@ -272,3 +338,10 @@ static int hb_unsharp_work(hb_filter_object_t *filter, return HB_FILTER_OK; } + +static int unsharp_work(hb_filter_object_t *filter, + hb_buffer_t ** buf_in, + hb_buffer_t ** buf_out) +{ + return unsharp_work_thread(filter, buf_in, buf_out, 0); +} |