summaryrefslogtreecommitdiff
path: root/yuvbench/yuvbench_accelerate.c
blob: 5f2e794ab5ee25640acfc0c16dbeb3d20920483c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
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;
}