Transpose first in chunks of 8x8 blocks. 15% faster overall.
Unified · Split
| @@ -58,6 +58,12 @@ typedef struct TransContext { · 57 unmodified lines | |||
| 58 | 58 | ||
| 59 | int passthrough; ///< PassthroughType, landscape passthrough mode enabled | 59 | int passthrough; ///< PassthroughType, landscape passthrough mode enabled |
| 60 | int dir; ///< TransposeDir | 60 | int dir; ///< TransposeDir |
| 61 | |||
| 62 | void (*transpose_8x8)(uint8_t *src, ptrdiff_t src_linesize, | ||
| 63 | uint8_t *dst, ptrdiff_t dst_linesize); | ||
| 64 | void (*transpose_block)(uint8_t *src, ptrdiff_t src_linesize, | ||
| 65 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
| 66 | int w, int h); | ||
| 61 | } TransContext; | 67 | } TransContext; |
| 62 | 68 | ||
| 63 | static int query_formats(AVFilterContext *ctx) | 69 | static int query_formats(AVFilterContext *ctx) |
| @@ -79,6 +85,109 @@ static int query_formats(AVFilterContext *ctx) · 15 unmodified lines | |||
| 79 | return ff_set_common_formats(ctx, pix_fmts); | 85 | return ff_set_common_formats(ctx, pix_fmts); |
| 80 | } | 86 | } |
| 81 | 87 | ||
| 88 | static inline void transpose_block_8_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 89 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
| 90 | int w, int h) | ||
| 91 | { | ||
| 92 | int x, y; | ||
| 93 | for (y = 0; y < h; y++, dst += dst_linesize, src++) | ||
| 94 | for (x = 0; x < w; x++) | ||
| 95 | dst[x] = src[x*src_linesize]; | ||
| 96 | } | ||
| 97 | |||
| 98 | static void transpose_8x8_8_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 99 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
| 100 | { | ||
| 101 | transpose_block_8_c(src, src_linesize, dst, dst_linesize, 8, 8); | ||
| 102 | } | ||
| 103 | |||
| 104 | static inline void transpose_block_16_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 105 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
| 106 | int w, int h) | ||
| 107 | { | ||
| 108 | int x, y; | ||
| 109 | for (y = 0; y < h; y++, dst += dst_linesize, src += 2) | ||
| 110 | for (x = 0; x < w; x++) | ||
| 111 | *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*src_linesize)); | ||
| 112 | } | ||
| 113 | |||
| 114 | static void transpose_8x8_16_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 115 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
| 116 | { | ||
| 117 | transpose_block_16_c(src, src_linesize, dst, dst_linesize, 8, 8); | ||
| 118 | } | ||
| 119 | |||
| 120 | static inline void transpose_block_24_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 121 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
| 122 | int w, int h) | ||
| 123 | { | ||
| 124 | int x, y; | ||
| 125 | for (y = 0; y < h; y++, dst += dst_linesize) { | ||
| 126 | for (x = 0; x < w; x++) { | ||
| 127 | int32_t v = AV_RB24(src + x*src_linesize + y*3); | ||
| 128 | AV_WB24(dst + 3*x, v); | ||
| 129 | } | ||
| 130 | } | ||
| 131 | } | ||
| 132 | |||
| 133 | static void transpose_8x8_24_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 134 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
| 135 | { | ||
| 136 | transpose_block_24_c(src, src_linesize, dst, dst_linesize, 8, 8); | ||
| 137 | } | ||
| 138 | |||
| 139 | static inline void transpose_block_32_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 140 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
| 141 | int w, int h) | ||
| 142 | { | ||
| 143 | int x, y; | ||
| 144 | for (y = 0; y < h; y++, dst += dst_linesize, src += 4) { | ||
| 145 | for (x = 0; x < w; x++) | ||
| 146 | *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*src_linesize)); | ||
| 147 | } | ||
| 148 | } | ||
| 149 | |||
| 150 | static void transpose_8x8_32_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 151 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
| 152 | { | ||
| 153 | transpose_block_32_c(src, src_linesize, dst, dst_linesize, 8, 8); | ||
| 154 | } | ||
| 155 | |||
| 156 | static inline void transpose_block_48_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 157 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
| 158 | int w, int h) | ||
| 159 | { | ||
| 160 | int x, y; | ||
| 161 | for (y = 0; y < h; y++, dst += dst_linesize, src += 6) { | ||
| 162 | for (x = 0; x < w; x++) { | ||
| 163 | int64_t v = AV_RB48(src + x*src_linesize); | ||
| 164 | AV_WB48(dst + 6*x, v); | ||
| 165 | } | ||
| 166 | } | ||
| 167 | } | ||
| 168 | |||
| 169 | static void transpose_8x8_48_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 170 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
| 171 | { | ||
| 172 | transpose_block_48_c(src, src_linesize, dst, dst_linesize, 8, 8); | ||
| 173 | } | ||
| 174 | |||
| 175 | static inline void transpose_block_64_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 176 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
| 177 | int w, int h) | ||
| 178 | { | ||
| 179 | int x, y; | ||
| 180 | for (y = 0; y < h; y++, dst += dst_linesize, src += 8) | ||
| 181 | for (x = 0; x < w; x++) | ||
| 182 | *((uint64_t *)(dst + 8*x)) = *((uint64_t *)(src + x*src_linesize)); | ||
| 183 | } | ||
| 184 | |||
| 185 | static void transpose_8x8_64_c(uint8_t *src, ptrdiff_t src_linesize, | ||
| 186 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
| 187 | { | ||
| 188 | transpose_block_64_c(src, src_linesize, dst, dst_linesize, 8, 8); | ||
| 189 | } | ||
| 190 | |||
| 82 | static int config_props_output(AVFilterLink *outlink) | 191 | static int config_props_output(AVFilterLink *outlink) |
| 83 | { | 192 | { |
| 84 | AVFilterContext *ctx = outlink->src; | 193 | AVFilterContext *ctx = outlink->src; |
| @@ -118,6 +227,21 @@ static int config_props_output(AVFilterLink *outlink) · 33 unmodified lines | |||
| 118 | else | 227 | else |
| 119 | outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; | 228 | outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; |
| 120 | 229 | ||
| 230 | switch (s->pixsteps[0]) { | ||
| 231 | case 1: s->transpose_block = transpose_block_8_c; | ||
| 232 | s->transpose_8x8 = transpose_8x8_8_c; break; | ||
| 233 | case 2: s->transpose_block = transpose_block_16_c; | ||
| 234 | s->transpose_8x8 = transpose_8x8_16_c; break; | ||
| 235 | case 3: s->transpose_block = transpose_block_24_c; | ||
| 236 | s->transpose_8x8 = transpose_8x8_24_c; break; | ||
| 237 | case 4: s->transpose_block = transpose_block_32_c; | ||
| 238 | s->transpose_8x8 = transpose_8x8_32_c; break; | ||
| 239 | case 6: s->transpose_block = transpose_block_48_c; | ||
| 240 | s->transpose_8x8 = transpose_8x8_48_c; break; | ||
| 241 | case 8: s->transpose_block = transpose_block_64_c; | ||
| 242 | s->transpose_8x8 = transpose_8x8_64_c; break; | ||
| 243 | } | ||
| 244 | |||
| 121 | av_log(ctx, AV_LOG_VERBOSE, | 245 | av_log(ctx, AV_LOG_VERBOSE, |
| 122 | "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n", | 246 | "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n", |
| 123 | inlink->w, inlink->h, s->dir, outlink->w, outlink->h, | 247 | inlink->w, inlink->h, s->dir, outlink->w, outlink->h, |
| @@ -176,49 +300,25 @@ static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, · 52 unmodified lines | |||
| 176 | dstlinesize *= -1; | 300 | dstlinesize *= -1; |
| 177 | } | 301 | } |
| 178 | 302 | ||
| 179 | switch (pixstep) { | 303 | for (y = start; y < end - 7; y += 8) { |
| 180 | case 1: | 304 | for (x = 0; x < outw - 7; x += 8) { |
| 181 | for (y = start; y < end; y++, dst += dstlinesize) | 305 | s->transpose_8x8(src + x * srclinesize + y * pixstep, |
| 182 | for (x = 0; x < outw; x++) | 306 | srclinesize, |
| 183 | dst[x] = src[x * srclinesize + y]; | 307 | dst + (y - start) * dstlinesize + x * pixstep, |
| 184 | break; | 308 | dstlinesize); |
| 185 | case 2: | ||
| 186 | for (y = start; y < end; y++, dst += dstlinesize) { | ||
| 187 | for (x = 0; x < outw; x++) | ||
| 188 | *((uint16_t *)(dst + 2 * x)) = | ||
| 189 | *((uint16_t *)(src + x * srclinesize + y * 2)); | ||
| 190 | } | ||
| 191 | break; | ||
| 192 | case 3: | ||
| 193 | for (y = start; y < end; y++, dst += dstlinesize) { | ||
| 194 | for (x = 0; x < outw; x++) { | ||
| 195 | int32_t v = AV_RB24(src + x * srclinesize + y * 3); | ||
| 196 | AV_WB24(dst + 3 * x, v); | ||
| 197 | } | ||
| 198 | } | ||
| 199 | break; | ||
| 200 | case 4: | ||
| 201 | for (y = start; y < end; y++, dst += dstlinesize) { | ||
| 202 | for (x = 0; x < outw; x++) | ||
| 203 | *((uint32_t *)(dst + 4 * x)) = | ||
| 204 | *((uint32_t *)(src + x * srclinesize + y * 4)); | ||
| 205 | } | 309 | } |
| 206 | break; | 310 | if (outw - x > 0 && end - y > 0) |
| 207 | case 6: | 311 | s->transpose_block(src + x * srclinesize + y * pixstep, |
| 208 | for (y = start; y < end; y++, dst += dstlinesize) { | 312 | srclinesize, |
| 209 | for (x = 0; x < outw; x++) { | 313 | dst + (y - start) * dstlinesize + x * pixstep, |
| 210 | int64_t v = AV_RB48(src + x * srclinesize + y*6); | 314 | dstlinesize, outw - x, end - y); |
| 211 | AV_WB48(dst + 6*x, v); | ||
| 212 | } | ||
| 213 | } | ||
| 214 | break; | ||
| 215 | case 8: | ||
| 216 | for (y = start; y < end; y++, dst += dstlinesize) { | ||
| 217 | for (x = 0; x < outw; x++) | ||
| 218 | *((uint64_t *)(dst + 8*x)) = *((uint64_t *)(src + x * srclinesize + y*8)); | ||
| 219 | } | ||
| 220 | break; | ||
| 221 | } | 315 | } |
| 316 | |||
| 317 | if (end - y > 0) | ||
| 318 | s->transpose_block(src + 0 * srclinesize + y * pixstep, | ||
| 319 | srclinesize, | ||
| 320 | dst + (y - start) * dstlinesize + 0 * pixstep, | ||
| 321 | dstlinesize, outw, end - y); | ||
| 222 | } | 322 | } |
| 223 | 323 | ||
| 224 | return 0; | 324 | return 0; |