| @@ -57,81 +57,90 @@ typedef struct TheadData { · 56 unmodified lines |
| 57 | 57 | int height; |
| 58 | 58 | } ThreadData; |
| 59 | 59 | |
| 60 | | −static int unsharp_slice(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) |
| 61 | | −{ |
| 62 | | − ThreadData *td = arg; |
| 63 | | − UnsharpFilterParam *fp = td->fp; |
| 64 | | − uint32_t **sc = fp->sc; |
| 65 | | − uint32_t *sr = fp->sr; |
| 66 | | − const uint8_t *src2 = NULL; //silence a warning |
| 67 | | − const int amount = fp->amount; |
| 68 | | − const int steps_x = fp->steps_x; |
| 69 | | − const int steps_y = fp->steps_y; |
| 70 | | − const int scalebits = fp->scalebits; |
| 71 | | − const int32_t halfscale = fp->halfscale; |
| 72 | | − |
| 73 | | − uint8_t *dst = td->dst; |
| 74 | | − const uint8_t *src = td->src; |
| 75 | | − const int dst_stride = td->dst_stride; |
| 76 | | − const int src_stride = td->src_stride; |
| 77 | | − const int width = td->width; |
| 78 | | − const int height = td->height; |
| 79 | | − const int sc_offset = jobnr * 2 * steps_y; |
| 80 | | − const int sr_offset = jobnr * (MAX_MATRIX_SIZE - 1); |
| 81 | | − const int slice_start = (height * jobnr) / nb_jobs; |
| 82 | | − const int slice_end = (height * (jobnr+1)) / nb_jobs; |
| 83 | | − |
| 84 | | − int32_t res; |
| 85 | | − int x, y, z; |
| 86 | | − uint32_t tmp1, tmp2; |
| 87 | | − |
| 88 | | − if (!amount) { |
| 89 | | − av_image_copy_plane(dst + slice_start * dst_stride, dst_stride, |
| 90 | | − src + slice_start * src_stride, src_stride, |
| 91 | | − width, slice_end - slice_start); |
| 92 | | − return 0; |
| 93 | | − } |
| 94 | | − |
| 95 | | − for (y = 0; y < 2 * steps_y; y++) |
| 96 | | − memset(sc[sc_offset + y], 0, sizeof(sc[y][0]) * (width + 2 * steps_x)); |
| 97 | | − |
| 98 | | − // if this is not the first tile, we start from (slice_start - steps_y), |
| 99 | | − // so we can get smooth result at slice boundary |
| 100 | | − if (slice_start > steps_y) { |
| 101 | | − src += (slice_start - steps_y) * src_stride; |
| 102 | | − dst += (slice_start - steps_y) * dst_stride; |
| 103 | | − } |
| 104 | | − |
| 105 | | − for (y = -steps_y + slice_start; y < steps_y + slice_end; y++) { |
| 106 | | − if (y < height) |
| 107 | | − src2 = src; |
| 108 | | − |
| 109 | | − memset(sr + sr_offset, 0, sizeof(sr[0]) * (2 * steps_x - 1)); |
| 110 | | − for (x = -steps_x; x < width + steps_x; x++) { |
| 111 | | − tmp1 = x <= 0 ? src2[0] : x >= width ? src2[width-1] : src2[x]; |
| 112 | | − for (z = 0; z < steps_x * 2; z += 2) { |
| 113 | | − tmp2 = sr[sr_offset + z + 0] + tmp1; sr[sr_offset + z + 0] = tmp1; |
| 114 | | − tmp1 = sr[sr_offset + z + 1] + tmp2; sr[sr_offset + z + 1] = tmp2; |
| 115 | | − } |
| 116 | | − for (z = 0; z < steps_y * 2; z += 2) { |
| 117 | | − tmp2 = sc[sc_offset + z + 0][x + steps_x] + tmp1; sc[sc_offset + z + 0][x + steps_x] = tmp1; |
| 118 | | − tmp1 = sc[sc_offset + z + 1][x + steps_x] + tmp2; sc[sc_offset + z + 1][x + steps_x] = tmp2; |
| 119 | | − } |
| 120 | | − if (x >= steps_x && y >= (steps_y + slice_start)) { |
| 121 | | − const uint8_t *srx = src - steps_y * src_stride + x - steps_x; |
| 122 | | − uint8_t *dsx = dst - steps_y * dst_stride + x - steps_x; |
| 123 | | − |
| 124 | | − res = (int32_t)*srx + ((((int32_t) * srx - (int32_t)((tmp1 + halfscale) >> scalebits)) * amount) >> 16); |
| 125 | | − *dsx = av_clip_uint8(res); |
| 126 | | − } |
| 127 | | − } |
| 128 | | − if (y >= 0) { |
| 129 | | − dst += dst_stride; |
| 130 | | − src += src_stride; |
| 131 | | − } |
| 132 | | − } |
| 133 | | − return 0; |
| 60 | +#define DEF_UNSHARP_SLICE_FUNC(name, nbits) \ |
| 61 | +static int name##_##nbits(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \ |
| 62 | +{ \ |
| 63 | + ThreadData *td = arg; \ |
| 64 | + UnsharpFilterParam *fp = td->fp; \ |
| 65 | + UnsharpContext *s = ctx->priv; \ |
| 66 | + uint32_t **sc = fp->sc; \ |
| 67 | + uint32_t *sr = fp->sr; \ |
| 68 | + const uint##nbits##_t *src2 = NULL; \ |
| 69 | + const int amount = fp->amount; \ |
| 70 | + const int steps_x = fp->steps_x; \ |
| 71 | + const int steps_y = fp->steps_y; \ |
| 72 | + const int scalebits = fp->scalebits; \ |
| 73 | + const int32_t halfscale = fp->halfscale; \ |
| 74 | + \ |
| 75 | + uint##nbits##_t *dst = (uint##nbits##_t*)td->dst; \ |
| 76 | + const uint##nbits##_t *src = (const uint##nbits##_t *)td->src; \ |
| 77 | + int dst_stride = td->dst_stride; \ |
| 78 | + int src_stride = td->src_stride; \ |
| 79 | + const int width = td->width; \ |
| 80 | + const int height = td->height; \ |
| 81 | + const int sc_offset = jobnr * 2 * steps_y; \ |
| 82 | + const int sr_offset = jobnr * (MAX_MATRIX_SIZE - 1); \ |
| 83 | + const int slice_start = (height * jobnr) / nb_jobs; \ |
| 84 | + const int slice_end = (height * (jobnr+1)) / nb_jobs; \ |
| 85 | + \ |
| 86 | + int32_t res; \ |
| 87 | + int x, y, z; \ |
| 88 | + uint32_t tmp1, tmp2; \ |
| 89 | + \ |
| 90 | + if (!amount) { \ |
| 91 | + av_image_copy_plane(td->dst + slice_start * dst_stride, dst_stride, \ |
| 92 | + td->src + slice_start * src_stride, src_stride, \ |
| 93 | + width * s->bps, slice_end - slice_start); \ |
| 94 | + return 0; \ |
| 95 | + } \ |
| 96 | + \ |
| 97 | + for (y = 0; y < 2 * steps_y; y++) \ |
| 98 | + memset(sc[sc_offset + y], 0, sizeof(sc[y][0]) * (width + 2 * steps_x)); \ |
| 99 | + \ |
| 100 | + dst_stride = dst_stride / s->bps; \ |
| 101 | + src_stride = src_stride / s->bps; \ |
| 102 | + /* if this is not the first tile, we start from (slice_start - steps_y) */ \ |
| 103 | + /* so we can get smooth result at slice boundary */ \ |
| 104 | + if (slice_start > steps_y) { \ |
| 105 | + src += (slice_start - steps_y) * src_stride; \ |
| 106 | + dst += (slice_start - steps_y) * dst_stride; \ |
| 107 | + } \ |
| 108 | + \ |
| 109 | + for (y = -steps_y + slice_start; y < steps_y + slice_end; y++) { \ |
| 110 | + if (y < height) \ |
| 111 | + src2 = src; \ |
| 112 | + \ |
| 113 | + memset(sr + sr_offset, 0, sizeof(sr[0]) * (2 * steps_x - 1)); \ |
| 114 | + for (x = -steps_x; x < width + steps_x; x++) { \ |
| 115 | + tmp1 = x <= 0 ? src2[0] : x >= width ? src2[width-1] : src2[x]; \ |
| 116 | + for (z = 0; z < steps_x * 2; z += 2) { \ |
| 117 | + tmp2 = sr[sr_offset + z + 0] + tmp1; sr[sr_offset + z + 0] = tmp1; \ |
| 118 | + tmp1 = sr[sr_offset + z + 1] + tmp2; sr[sr_offset + z + 1] = tmp2; \ |
| 119 | + } \ |
| 120 | + for (z = 0; z < steps_y * 2; z += 2) { \ |
| 121 | + tmp2 = sc[sc_offset + z + 0][x + steps_x] + tmp1; \ |
| 122 | + sc[sc_offset + z + 0][x + steps_x] = tmp1; \ |
| 123 | + tmp1 = sc[sc_offset + z + 1][x + steps_x] + tmp2; \ |
| 124 | + sc[sc_offset + z + 1][x + steps_x] = tmp2; \ |
| 125 | + } \ |
| 126 | + if (x >= steps_x && y >= (steps_y + slice_start)) { \ |
| 127 | + const uint##nbits##_t *srx = src - steps_y * src_stride + x - steps_x; \ |
| 128 | + uint##nbits##_t *dsx = dst - steps_y * dst_stride + x - steps_x; \ |
| 129 | + \ |
| 130 | + res = (int32_t)*srx + ((((int32_t) * srx - \ |
| 131 | + (int32_t)((tmp1 + halfscale) >> scalebits)) * amount) >> (8+nbits)); \ |
| 132 | + *dsx = av_clip_uint##nbits(res); \ |
| 133 | + } \ |
| 134 | + } \ |
| 135 | + if (y >= 0) { \ |
| 136 | + dst += dst_stride; \ |
| 137 | + src += src_stride; \ |
| 138 | + } \ |
| 139 | + } \ |
| 140 | + return 0; \ |
| 134 | 141 | } |
| 142 | +DEF_UNSHARP_SLICE_FUNC(unsharp_slice, 16); |
| 143 | +DEF_UNSHARP_SLICE_FUNC(unsharp_slice, 8); |
| 135 | 144 | |
| 136 | 145 | static int apply_unsharp_c(AVFilterContext *ctx, AVFrame *in, AVFrame *out) |
| 137 | 146 | { |
| @@ -155,7 +164,7 @@ static int apply_unsharp_c(AVFilterContext *ctx, AVFrame *in, AVFrame *out) · 17 unmodified lines |
| 155 | 164 | td.height = plane_h[i]; |
| 156 | 165 | td.dst_stride = out->linesize[i]; |
| 157 | 166 | td.src_stride = in->linesize[i]; |
| 158 | | − ctx->internal->execute(ctx, unsharp_slice, &td, NULL, FFMIN(plane_h[i], s->nb_threads)); |
| 167 | + ctx->internal->execute(ctx, s->unsharp_slice, &td, NULL, FFMIN(plane_h[i], s->nb_threads)); |
| 159 | 168 | } |
| 160 | 169 | return 0; |
| 161 | 170 | } |
| @@ -238,6 +247,9 @@ static int config_input(AVFilterLink *inlink) · 76 unmodified lines |
| 238 | 247 | |
| 239 | 248 | s->hsub = desc->log2_chroma_w; |
| 240 | 249 | s->vsub = desc->log2_chroma_h; |
| 250 | + s->bitdepth = desc->comp[0].depth; |
| 251 | + s->bps = s->bitdepth > 8 ? 2 : 1; |
| 252 | + s->unsharp_slice = s->bitdepth > 8 ? unsharp_slice_16 : unsharp_slice_8; |
| 241 | 253 | |
| 242 | 254 | // ensure (height / nb_threads) > 4 * steps_y, |
| 243 | 255 | // so that we don't have too much overlap between two threads |