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
|
#include "yuvbench.h"
#include <Accelerate/Accelerate.h>
typedef struct AccelerateCtx AccelerateCtx;
struct AccelerateCtx
{
void* rgba_buf;
vImage_YpCbCrToARGB conv;
};
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;
// 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;
//
if (vImageConvert_YpCbCrToARGB_GenerateConversion(&matrix, &pr, &accel->conv, kvImage420Yp8_Cb8_Cr8, kvImageARGB8888, kvImageNoFlags) != kvImageNoError) {
return false;
}
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);
//
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, &accel->conv, 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;
}
|