summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLauri Kasanen <cand@gmx.com>2019-04-30 14:25:38 +0300
committerLauri Kasanen <cand@gmx.com>2019-05-07 10:08:16 +0300
commita2a16206aa1dc2cc594d605c74d5524fdb02efb0 (patch)
tree9ff9798a1aec1c28eaeb308773a23f042a9ab8ae
parent3437111f17dbef8c5f432798d45e354eccf1705d (diff)
downloadffmpeg-streaming-a2a16206aa1dc2cc594d605c74d5524fdb02efb0.zip
ffmpeg-streaming-a2a16206aa1dc2cc594d605c74d5524fdb02efb0.tar.gz
swscale/ppc: VSX-optimize hScale16To*
./ffmpeg -loop 1 -s 1200x1440 -i tux16.png \ -s 2400x720 -f rawvideo -y -vframes 5 -pix_fmt yuv420p16le -nostats test.raw ./ffmpeg -loop 1 -s 1200x1440 -i tux16.png \ -s 2400x720 -f rawvideo -y -vframes 5 -pix_fmt yuv420p -nostats test.raw 32-bit mul, power8 only 2x speedup for hScale8To19_vsx (x86 SSE2 is 2.37): 30896 UNITS in hscale, 8192 runs, 0 skips 63956 UNITS in hscale, 8192 runs, 0 skips 2.06 for hScale16To15_vsx: 30531 UNITS in hscale, 8192 runs, 0 skips 63161 UNITS in hscale, 8192 runs, 0 skips
-rw-r--r--libswscale/ppc/swscale_vsx.c159
1 files changed, 159 insertions, 0 deletions
diff --git a/libswscale/ppc/swscale_vsx.c b/libswscale/ppc/swscale_vsx.c
index 17c15a2..31d3ba2 100644
--- a/libswscale/ppc/swscale_vsx.c
+++ b/libswscale/ppc/swscale_vsx.c
@@ -1911,6 +1911,160 @@ static void hScale8To19_vsx(SwsContext *c, int16_t *_dst, int dstW,
}
}
+static void hScale16To19_vsx(SwsContext *c, int16_t *_dst, int dstW,
+ const uint8_t *_src, const int16_t *filter,
+ const int32_t *filterPos, int filterSize)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+ int i, j;
+ int32_t *dst = (int32_t *) _dst;
+ const uint16_t *src = (const uint16_t *) _src;
+ int bits = desc->comp[0].depth - 1;
+ int sh = bits - 4;
+ vector int16_t vfilter, vin;
+ vector int32_t vout, vtmp, vtmp2, vfilter32_l, vfilter32_r;
+ const vector uint8_t vzero = vec_splat_u8(0);
+ const vector uint8_t vunusedtab[8] = {
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf},
+ (vector uint8_t) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10},
+ };
+ const vector uint8_t vunused = vunusedtab[filterSize % 8];
+
+ if ((isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8) && desc->comp[0].depth<16) {
+ sh = 9;
+ } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
+ sh = 16 - 1 - 4;
+ }
+
+ if (filterSize == 1) {
+ for (i = 0; i < dstW; i++) {
+ int srcPos = filterPos[i];
+ int val = 0;
+
+ for (j = 0; j < filterSize; j++) {
+ val += src[srcPos + j] * filter[filterSize * i + j];
+ }
+ // filter=14 bit, input=16 bit, output=30 bit, >> 11 makes 19 bit
+ dst[i] = FFMIN(val >> sh, (1 << 19) - 1);
+ }
+ } else {
+ for (i = 0; i < dstW; i++) {
+ const int srcPos = filterPos[i];
+ vout = vec_splat_s32(0);
+ for (j = 0; j < filterSize; j += 8) {
+ vin = (vector int16_t) vec_vsx_ld(0, &src[srcPos + j]);
+ if (j + 8 > filterSize) // Remove the unused elements on the last round
+ vin = vec_perm(vin, (vector int16_t) vzero, vunused);
+
+ vfilter = vec_vsx_ld(0, &filter[filterSize * i + j]);
+ vfilter32_l = vec_unpackh(vfilter);
+ vfilter32_r = vec_unpackl(vfilter);
+
+ vtmp = (vector int32_t) vec_mergeh(vin, (vector int16_t) vzero);
+ vtmp2 = (vector int32_t) vec_mergel(vin, (vector int16_t) vzero);
+
+ vtmp = vec_mul(vtmp, vfilter32_l);
+ vtmp2 = vec_mul(vtmp2, vfilter32_r);
+
+ vout = vec_adds(vout, vtmp);
+ vout = vec_adds(vout, vtmp2);
+ }
+ vout = vec_sums(vout, (vector int32_t) vzero);
+ dst[i] = FFMIN(vout[3] >> sh, (1 << 19) - 1);
+ }
+ }
+}
+
+static void hScale16To15_vsx(SwsContext *c, int16_t *dst, int dstW,
+ const uint8_t *_src, const int16_t *filter,
+ const int32_t *filterPos, int filterSize)
+{
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(c->srcFormat);
+ int i, j;
+ const uint16_t *src = (const uint16_t *) _src;
+ int sh = desc->comp[0].depth - 1;
+ vector int16_t vfilter, vin;
+ vector int32_t vout, vtmp, vtmp2, vfilter32_l, vfilter32_r;
+ const vector uint8_t vzero = vec_splat_u8(0);
+ const vector uint8_t vunusedtab[8] = {
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf},
+ (vector uint8_t) {0x0, 0x1, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x10, 0x10, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x10, 0x10,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0x10, 0x10, 0x10, 0x10},
+ (vector uint8_t) {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7,
+ 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0x10, 0x10},
+ };
+ const vector uint8_t vunused = vunusedtab[filterSize % 8];
+
+ if (sh<15) {
+ sh = isAnyRGB(c->srcFormat) || c->srcFormat==AV_PIX_FMT_PAL8 ? 13 : (desc->comp[0].depth - 1);
+ } else if (desc->flags & AV_PIX_FMT_FLAG_FLOAT) { /* float input are process like uint 16bpc */
+ sh = 16 - 1;
+ }
+
+ if (filterSize == 1) {
+ for (i = 0; i < dstW; i++) {
+ int srcPos = filterPos[i];
+ int val = 0;
+
+ for (j = 0; j < filterSize; j++) {
+ val += src[srcPos + j] * filter[filterSize * i + j];
+ }
+ // filter=14 bit, input=16 bit, output=30 bit, >> 15 makes 15 bit
+ dst[i] = FFMIN(val >> sh, (1 << 15) - 1);
+ }
+ } else {
+ for (i = 0; i < dstW; i++) {
+ const int srcPos = filterPos[i];
+ vout = vec_splat_s32(0);
+ for (j = 0; j < filterSize; j += 8) {
+ vin = (vector int16_t) vec_vsx_ld(0, &src[srcPos + j]);
+ if (j + 8 > filterSize) // Remove the unused elements on the last round
+ vin = vec_perm(vin, (vector int16_t) vzero, vunused);
+
+ vfilter = vec_vsx_ld(0, &filter[filterSize * i + j]);
+ vfilter32_l = vec_unpackh(vfilter);
+ vfilter32_r = vec_unpackl(vfilter);
+
+ vtmp = (vector int32_t) vec_mergeh(vin, (vector int16_t) vzero);
+ vtmp2 = (vector int32_t) vec_mergel(vin, (vector int16_t) vzero);
+
+ vtmp = vec_mul(vtmp, vfilter32_l);
+ vtmp2 = vec_mul(vtmp2, vfilter32_r);
+
+ vout = vec_adds(vout, vtmp);
+ vout = vec_adds(vout, vtmp2);
+ }
+ vout = vec_sums(vout, (vector int32_t) vzero);
+ dst[i] = FFMIN(vout[3] >> sh, (1 << 15) - 1);
+ }
+ }
+}
+
#endif /* !HAVE_BIGENDIAN */
#endif /* HAVE_VSX */
@@ -1935,6 +2089,11 @@ av_cold void ff_sws_init_swscale_vsx(SwsContext *c)
} else {
c->hyScale = c->hcScale = hScale8To19_vsx;
}
+ } else {
+ if (HAVE_POWER8 && cpu_flags & AV_CPU_FLAG_POWER8) {
+ c->hyScale = c->hcScale = c->dstBpc > 14 ? hScale16To19_vsx
+ : hScale16To15_vsx;
+ }
}
if (!is16BPS(dstFormat) && !isNBPS(dstFormat) &&
dstFormat != AV_PIX_FMT_NV12 && dstFormat != AV_PIX_FMT_NV21 &&
OpenPOWER on IntegriCloud