summaryrefslogtreecommitdiff
path: root/yuvbench/yuvbench_accelerate.c
diff options
context:
space:
mode:
Diffstat (limited to 'yuvbench/yuvbench_accelerate.c')
-rw-r--r--yuvbench/yuvbench_accelerate.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/yuvbench/yuvbench_accelerate.c b/yuvbench/yuvbench_accelerate.c
new file mode 100644
index 0000000..5f2e794
--- /dev/null
+++ b/yuvbench/yuvbench_accelerate.c
@@ -0,0 +1,103 @@
+#include "yuvbench.h"
+
+#include <Accelerate/Accelerate.h>
+
+typedef struct AccelerateCtx AccelerateCtx;
+struct AccelerateCtx
+{
+ void* rgba_buf;
+};
+
+static bool yuvbench_accelerate_init(Ctx* ctx)
+{
+ AccelerateCtx* accel = calloc(1, sizeof(AccelerateCtx));
+ accel->rgba_buf = calloc(4, ctx->inp_w * ctx->inp_h);
+ ctx->user = accel;
+ return true;
+}
+
+static void yuvbench_accelerate_deinit(Ctx* ctx)
+{
+ AccelerateCtx* accel = (AccelerateCtx*)ctx->user;
+ free(accel->rgba_buf);
+ free(accel);
+}
+
+static bool yuvbench_accelerate_convert(Ctx* ctx)
+{
+ AccelerateCtx* accel = (AccelerateCtx*)ctx->user;
+ const uint32_t w = ctx->inp_w;
+ const uint32_t h = ctx->inp_h;
+ const uint8_t* Y = (const uint8_t*)ctx->inp_buf;
+ const uint8_t* Cb = Y + (w * h);
+ const uint8_t* Cr = Cb + (w / 2 * h / 2);
+ // BT.709
+ vImage_YpCbCrToARGBMatrix matrix = { 0 };
+ matrix.Yp = 1.0f;
+ matrix.Cb_G = -0.1873f;
+ matrix.Cb_B = 1.8556f;
+ matrix.Cr_R = 1.5748f;
+ matrix.Cr_G = -0.4681f;
+ //
+ vImage_YpCbCrPixelRange pr = { 0 };
+ pr.Yp_bias = 16;
+ pr.CbCr_bias = 128;
+ pr.YpRangeMax = 235;
+ pr.CbCrRangeMax = 240;
+ pr.YpMax = 235;
+ pr.YpMin = 16;
+ pr.CbCrMax = 240;
+ pr.CbCrMin = 16;
+ //
+ vImage_YpCbCrToARGB out = { 0 };
+ //
+ if (vImageConvert_YpCbCrToARGB_GenerateConversion(&matrix, &pr, &out, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, kvImageNoFlags) != kvImageNoError) {
+ return false;
+ }
+ //
+ vImage_Buffer ypbuf = { 0 };
+ ypbuf.data = (void*)Y;
+ ypbuf.width = w;
+ ypbuf.height = h;
+ ypbuf.rowBytes = w;
+ vImage_Buffer cbbuf = { 0 };
+ cbbuf.data = (void*)Cb;
+ cbbuf.width = w / 2;
+ cbbuf.height = h / 2;
+ cbbuf.rowBytes = w / 2;
+ vImage_Buffer crbuf = { 0 };
+ crbuf.data = (void*)Cr;
+ crbuf.width = w / 2;
+ crbuf.height = h / 2;
+ crbuf.rowBytes = w / 2;
+ vImage_Buffer rgbabuf = { 0 };
+ rgbabuf.data = accel->rgba_buf;
+ rgbabuf.width = w;
+ rgbabuf.height = h;
+ rgbabuf.rowBytes = w * 4;
+ //
+ uint8_t permute[4] = { 0, 1, 2, 3 };
+ //
+ if (vImageConvert_420Yp8_Cb8_Cr8ToARGB8888(&ypbuf, &cbbuf, &crbuf, &rgbabuf, &out, permute, 0xFF, kvImageNoFlags) != kvImageNoError) {
+ return false;
+ }
+ //
+ vImage_Buffer rgbbuf = { 0 };
+ rgbbuf.data = ctx->out_buf;
+ rgbbuf.width = w;
+ rgbbuf.height = h;
+ rgbbuf.rowBytes = w * 3;
+ if (vImageConvert_ARGB8888toRGB888(&rgbabuf, &rgbbuf, kvImageNoFlags) != kvImageNoError) {
+ return false;
+ }
+ return true;
+}
+
+Backend yuvbench_accelerate(void)
+{
+ Backend b = { 0 };
+ b.init_fn = yuvbench_accelerate_init;
+ b.deinit_fn = yuvbench_accelerate_deinit;
+ b.convert_fn = yuvbench_accelerate_convert;
+ return b;
+}