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