Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong
GitHub Repository: orangepi-xunlong/orangepi-build
Path: blob/next/external/packages/extras-buildpkgs/libvdpau-sunxi/debian/patches/redo-csc-calculations.patch
18313 views
1
diff --git a/csc.h b/csc.h
2
new file mode 100644
3
index 0000000..49705cc
4
--- /dev/null
5
+++ b/csc.h
6
@@ -0,0 +1,72 @@
7
+/*
8
+ * Copyright (c) 2015-2016 Andreas Baierl <[email protected]>
9
+ *
10
+ * This library is free software; you can redistribute it and/or
11
+ * modify it under the terms of the GNU Lesser General Public
12
+ * License as published by the Free Software Foundation; either
13
+ * version 2.1 of the License, or (at your option) any later version.
14
+ *
15
+ * This library is distributed in the hope that it will be useful,
16
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18
+ * Lesser General Public License for more details.
19
+ *
20
+ * You should have received a copy of the GNU Lesser General Public
21
+ * License along with this library; if not, write to the Free Software
22
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23
+ *
24
+ */
25
+
26
+#ifndef __CSC_H__
27
+#define __CSC_H__
28
+
29
+#include "vdpau_private.h"
30
+
31
+typedef float csc_m[3][4];
32
+
33
+#ifdef CSC_FULL_RANGE
34
+/*
35
+ * This matrizes are from vl_csc.c from the mesa project
36
+ * The calculation routines are there, too.
37
+ */
38
+
39
+/* Full range: RGB is in 0~255 */
40
+static const csc_m cs_bt601 = {
41
+ { 1.164f, 0.0f, 1.596f, 0.0f, },
42
+ { 1.164f, -0.391f, -0.813f, 0.0f, },
43
+ { 1.164f, 2.018f, 0.0f, 0.0f, }
44
+};
45
+static const csc_m cs_bt709 = {
46
+ { 1.164f, 0.0f, 1.793f, 0.0f, },
47
+ { 1.164f, -0.213f, -0.534f, 0.0f, },
48
+ { 1.164f, 2.115f, 0.0f, 0.0f, }
49
+};
50
+static const csc_m cs_smpte_240m = {
51
+ { 1.164f, 0.0f, 1.794f, 0.0f, },
52
+ { 1.164f, -0.258f, -0.543f, 0.0f, },
53
+ { 1.164f, 2.079f, 0.0f, 0.0f, }
54
+};
55
+const float ybias = -16.0f / 255.0f;
56
+#else
57
+/* Normal range: RGB is in 16~235 */
58
+static const csc_m cs_bt601 = {
59
+ { 1.0f, 0.0f, 1.371f, 0.0f, },
60
+ { 1.0f, -0.336f, -0.698f, 0.0f, },
61
+ { 1.0f, 1.732f, 0.0f, 0.0f, }
62
+};
63
+static const csc_m cs_bt709 = {
64
+ { 1.0f, 0.0f, 1.540f, 0.0f, },
65
+ { 1.0f, -0.183f, -0.459f, 0.0f, },
66
+ { 1.0f, 1.816f, 0.0f, 0.0f, }
67
+};
68
+static const csc_m cs_smpte_240m = {
69
+ { 1.0f, 0.0f, 1.582f, 0.0f, },
70
+ { 1.0f, -0.228f, -0.478f, 0.0f, },
71
+ { 1.0f, 1.833f, 0.0f, 0.0f, }
72
+};
73
+static const float ybias = 0.0f;
74
+#endif
75
+const float cbbias = -128.0f / 255.0f;
76
+const float crbias = -128.0f / 255.0f;
77
+
78
+#endif
79
diff --git a/sunxi_disp.c b/sunxi_disp.c
80
index 89a029b..6cd934f 100644
81
--- a/sunxi_disp.c
82
+++ b/sunxi_disp.c
83
@@ -21,6 +21,7 @@
84
#include <stdlib.h>
85
#include <stdint.h>
86
#include <unistd.h>
87
+#include <math.h>
88
#include <sys/ioctl.h>
89
#include "kernel-headers/sunxi_disp_ioctl.h"
90
#include "vdpau_private.h"
91
@@ -202,24 +203,38 @@ static int sunxi_disp_set_video_layer(struct sunxi_disp *sunxi_disp, int x, int
92
93
ioctl(disp->fd, DISP_CMD_LAYER_OPEN, args);
94
95
- // Note: might be more reliable (but slower and problematic when there
96
- // are driver issues and the GET functions return wrong values) to query the
97
- // old values instead of relying on our internal csc_change.
98
- // Since the driver calculates a matrix out of these values after each
99
- // set doing this unconditionally is costly.
100
if (surface->csc_change)
101
{
102
- ioctl(disp->fd, DISP_CMD_LAYER_ENHANCE_OFF, args);
103
- args[2] = 0xff * surface->brightness + 0x20;
104
- ioctl(disp->fd, DISP_CMD_LAYER_SET_BRIGHT, args);
105
- args[2] = 0x20 * surface->contrast;
106
- ioctl(disp->fd, DISP_CMD_LAYER_SET_CONTRAST, args);
107
- args[2] = 0x20 * surface->saturation;
108
- ioctl(disp->fd, DISP_CMD_LAYER_SET_SATURATION, args);
109
- // hue scale is randomly chosen, no idea how it maps exactly
110
- args[2] = (32 / 3.14) * surface->hue + 0x20;
111
- ioctl(disp->fd, DISP_CMD_LAYER_SET_HUE, args);
112
- ioctl(disp->fd, DISP_CMD_LAYER_ENHANCE_ON, args);
113
+ uint32_t b, c, s, h;
114
+
115
+ /* ioctl(disp->fd, DISP_CMD_LAYER_ENHANCE_OFF, args); */
116
+
117
+ /* scale VDPAU: -1.0 ~ 1.0 to SUNXI: 0 ~ 100 */
118
+ b = args[2] = ((surface->brightness + 1.0) * 50.0) + 0.5;
119
+ /* ioctl(disp->fd, DISP_CMD_LAYER_SET_BRIGHT, args); */
120
+
121
+ /* scale VDPAU: 0.0 ~ 10.0 to SUNXI: 0 ~ 100 */
122
+ if (surface->contrast <= 1.0)
123
+ c = args[2] = (surface->contrast * 50.0) + 0.5;
124
+ else
125
+ c = args[2] = (50.0 + (surface->contrast - 1.0) * 50.0 / 9.0) + 0.5;
126
+ /* ioctl(disp->fd, DISP_CMD_LAYER_SET_CONTRAST, args); */
127
+
128
+ /* scale VDPAU: 0.0 ~ 10.0 to SUNXI: 0 ~ 100 */
129
+ if (surface->saturation <= 1.0)
130
+ s = args[2] = (surface->saturation * 50.0) + 0.5;
131
+ else
132
+ s = args[2] = (50.0 + (surface->saturation - 1.0) * 50.0 / 9.0) + 0.5;
133
+ /* ioctl(disp->fd, DISP_CMD_LAYER_SET_SATURATION, args); */
134
+
135
+ /* scale VDPAU: -PI ~ PI to SUNXI: 0 ~ 100 */
136
+ h = args[2] = (((surface->hue / M_PI) + 1.0) * 50.0) + 0.5;
137
+ /* ioctl(disp->fd, DISP_CMD_LAYER_SET_HUE, args); */
138
+
139
+ /* ioctl(disp->fd, DISP_CMD_LAYER_ENHANCE_ON, args); */
140
+ VDPAU_DBG("Presentation queue csc change");
141
+ VDPAU_DBG("display driver -> bright: %d, contrast: %d, saturation: %d, hue: %d", b, c, s, h);
142
+ VDPAU_DBG("Not changing display settings to workaround csc brightness bug");
143
surface->csc_change = 0;
144
}
145
146
diff --git a/vdpau_private.h b/vdpau_private.h
147
index bb078ac..d3bdda5 100644
148
--- a/vdpau_private.h
149
+++ b/vdpau_private.h
150
@@ -22,6 +22,7 @@
151
152
#define DEBUG
153
#define MAX_HANDLES 64
154
+#define CSC_FULL_RANGE 1
155
#define VBV_SIZE (1 * 1024 * 1024)
156
157
#include <stdlib.h>
158
@@ -98,6 +99,8 @@ typedef struct
159
float contrast;
160
float saturation;
161
float hue;
162
+ int custom_csc;
163
+ VdpCSCMatrix csc_matrix;
164
} mixer_ctx_t;
165
166
#define RGBA_FLAG_DIRTY (1 << 0)
167
diff --git a/video_mixer.c b/video_mixer.c
168
index 9fd1ccc..cd65be3 100644
169
--- a/video_mixer.c
170
+++ b/video_mixer.c
171
@@ -18,9 +18,90 @@
172
*/
173
174
#include <math.h>
175
+#include <string.h>
176
#include <cedrus/cedrus.h>
177
#include "vdpau_private.h"
178
#include "rgba.h"
179
+#include "csc.h"
180
+
181
+static VdpColorStandard color_standard;
182
+
183
+static void set_csc_matrix(mixer_ctx_t *mix, VdpColorStandard standard)
184
+{
185
+ float asin;
186
+ static const csc_m *cstd;
187
+
188
+ mix->csc_change = 1;
189
+ switch (standard) {
190
+ case VDP_COLOR_STANDARD_ITUR_BT_709:
191
+ cstd = &cs_bt709;
192
+ break;
193
+ case VDP_COLOR_STANDARD_SMPTE_240M:
194
+ cstd = &cs_smpte_240m;
195
+ break;
196
+ case VDP_COLOR_STANDARD_ITUR_BT_601:
197
+ default:
198
+ cstd = &cs_bt601;
199
+ break;
200
+ }
201
+ VdpCSCMatrix *matrix = &mix->csc_matrix;
202
+
203
+ if ((*matrix)[1][0] == 0 && (*matrix)[1][1] == 0 && (*matrix)[1][2] == 0)
204
+ {
205
+ /* At least contrast was 0.0f. Set Hue and saturation to default. They cannot be guessed... */
206
+ mix->contrast = 0.0f;
207
+ mix->hue = 0.0f;
208
+ mix->saturation = 1.0f;
209
+ }
210
+ else
211
+ {
212
+ /* Contrast */
213
+ mix->contrast = (*matrix)[0][0] / (*cstd)[0][0];
214
+
215
+ if ((*matrix)[1][1] == 0 && (*matrix)[1][2] == 0)
216
+ {
217
+ /* Saturation was 0.0f. Set Hue to default. This cannot be guessed... */
218
+ mix->hue = 0.0f;
219
+ mix->saturation = 0.0f;
220
+ }
221
+ else
222
+ {
223
+ /* Hue */
224
+ asin = asinf(sqrtf(pow(((*matrix)[1][1] * (*cstd)[1][2] - (*matrix)[1][2] * (*cstd)[1][1]), 2.0) /
225
+ (pow((-(*matrix)[1][1] * (*cstd)[1][1] - (*matrix)[1][2] * (*cstd)[1][2]), 2.0) +
226
+ pow(((*matrix)[1][1] * (*cstd)[1][2] - (*matrix)[1][2] * (*cstd)[1][1]), 2.0))));
227
+
228
+ if (((*matrix)[2][1] < 0 && (*cstd)[2][1] < 0) || ((*matrix)[2][1] > 0 && (*cstd)[2][1] > 0))
229
+ if (((*matrix)[0][1] < 0 && (*matrix)[0][2] > 0) || ((*matrix)[0][1] > 0 && (*matrix)[0][2] < 0))
230
+ mix->hue = asin;
231
+ else
232
+ mix->hue = - asin;
233
+ else
234
+ if (((*matrix)[0][1] < 0 && (*matrix)[0][2] > 0) || ((*matrix)[0][1] > 0 && (*matrix)[0][2] < 0))
235
+ mix->hue = - M_PI + asin;
236
+ else
237
+ mix->hue = M_PI - asin;
238
+
239
+ /* Check, if Hue was M_PI or -M_PI */
240
+ if ((fabs(fabs(mix->hue) - M_PI)) < 0.00001f)
241
+ mix->hue = - mix->hue;
242
+
243
+ /* Saturation */
244
+ mix->saturation = (*matrix)[1][1] / (mix->contrast * ((*cstd)[1][1] * cosf(mix->hue) - (*cstd)[1][2] * sinf(mix->hue)));
245
+ }
246
+ }
247
+
248
+ /* Brightness */
249
+ mix->brightness = ((*matrix)[1][3] -
250
+ (*cstd)[1][1] * mix->contrast * mix->saturation * (cbbias * cosf(mix->hue) + crbias * sinf(mix->hue)) -
251
+ (*cstd)[1][2] * mix->contrast * mix->saturation * (crbias * cosf(mix->hue) - cbbias * sinf(mix->hue)) -
252
+ (*cstd)[1][3] - (*cstd)[1][0] * mix->contrast * ybias) / (*cstd)[1][0];
253
+
254
+ VDPAU_DBG("Setting mixer value from following color standard: %d", standard);
255
+ VDPAU_DBG(">mix->bright: %2.3f, mix->contrast: %2.3f, mix->saturation: %2.3f, mix->hue: %2.3f",
256
+ (double)mix->brightness, (double)mix->contrast,
257
+ (double)mix->saturation, (double)mix->hue);
258
+}
259
260
VdpStatus vdp_video_mixer_create(VdpDevice device,
261
uint32_t feature_count,
262
@@ -39,8 +120,16 @@ VdpStatus vdp_video_mixer_create(VdpDevice device,
263
return VDP_STATUS_RESOURCES;
264
265
mix->device = dev;
266
+ mix->brightness = 0.0;
267
mix->contrast = 1.0;
268
mix->saturation = 1.0;
269
+ mix->hue = 0.0;
270
+
271
+ /* CSC: Use BT601 at initalization time */
272
+ mix->custom_csc = 0;
273
+ color_standard = VDP_COLOR_STANDARD_ITUR_BT_601;
274
+ vdp_generate_csc_matrix(NULL, color_standard, &mix->csc_matrix);
275
+ set_csc_matrix(mix, color_standard);
276
277
return VDP_STATUS_OK;
278
}
279
@@ -190,26 +279,6 @@ VdpStatus vdp_video_mixer_get_feature_enables(VdpVideoMixer mixer,
280
return VDP_STATUS_ERROR;
281
}
282
283
-static void set_csc_matrix(mixer_ctx_t *mix, const VdpCSCMatrix *matrix)
284
-{
285
- mix->csc_change = 1;
286
- // default contrast for full-range has 1.0 as luma coefficients
287
- mix->contrast = ((*matrix)[0][0] + (*matrix)[1][0] + (*matrix)[2][0]) / 3;
288
- // the way brightness and contrast work with this driver, brightness
289
- // is the brightness of a "black" pixel
290
- mix->brightness = ((*matrix)[0][1] + (*matrix)[1][1] + (*matrix)[2][1]) / 2 +
291
- ((*matrix)[0][2] + (*matrix)[1][2] + (*matrix)[2][2]) / 2 +
292
- (*matrix)[0][3] + (*matrix)[1][3] + (*matrix)[2][3];
293
- mix->brightness /= 3;
294
-
295
- float sin = (*matrix)[0][1] + (*matrix)[2][2];
296
- float cos = (*matrix)[0][2] + (*matrix)[2][1];
297
- float e = 0.001;
298
- if (-e < cos && cos < e) mix->hue = M_PI;
299
- else mix->hue = atanf(sin/cos);
300
- mix->saturation = sqrtf(sin * sin + cos * cos) / (1.403 + 1.773);
301
-}
302
-
303
VdpStatus vdp_video_mixer_set_attribute_values(VdpVideoMixer mixer,
304
uint32_t attribute_count,
305
VdpVideoMixerAttribute const *attributes,
306
@@ -223,9 +292,24 @@ VdpStatus vdp_video_mixer_set_attribute_values(VdpVideoMixer mixer,
307
return VDP_STATUS_INVALID_HANDLE;
308
309
uint32_t i;
310
- for (i = 0; i < attribute_count; i++)
311
- if (attributes[i] == VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX)
312
- set_csc_matrix(mix, (const VdpCSCMatrix *)attribute_values[i]);
313
+ for (i = 0; i < attribute_count; i++) {
314
+ switch (attributes[i]) {
315
+ case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
316
+ mix->custom_csc = !!attribute_values[i];
317
+ if (!attribute_values[i])
318
+ {
319
+ /* CSC: Use BT601 if not set */
320
+ color_standard = VDP_COLOR_STANDARD_ITUR_BT_601;
321
+ vdp_generate_csc_matrix(NULL, color_standard, &mix->csc_matrix);
322
+ }
323
+ else
324
+ memcpy(mix->csc_matrix, attribute_values[i], sizeof(mix->csc_matrix));
325
+ set_csc_matrix(mix, color_standard);
326
+ break;
327
+ default:
328
+ return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
329
+ }
330
+ }
331
332
return VDP_STATUS_OK;
333
}
334
@@ -251,6 +335,9 @@ VdpStatus vdp_video_mixer_get_attribute_values(VdpVideoMixer mixer,
335
VdpVideoMixerAttribute const *attributes,
336
void *const *attribute_values)
337
{
338
+ int i;
339
+ VdpCSCMatrix **vdp_csc;
340
+
341
if (!attributes || !attribute_values)
342
return VDP_STATUS_INVALID_POINTER;
343
344
@@ -258,8 +345,29 @@ VdpStatus vdp_video_mixer_get_attribute_values(VdpVideoMixer mixer,
345
if (!mix)
346
return VDP_STATUS_INVALID_HANDLE;
347
348
+ for (i = 0; i < attribute_count; i++) {
349
+ switch (attributes[i])
350
+ {
351
+ case VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX:
352
+ vdp_csc = attribute_values[i];
353
+ if (!mix->custom_csc)
354
+ *vdp_csc = NULL;
355
+ else
356
+ memcpy(*vdp_csc, mix->csc_matrix, sizeof(VdpCSCMatrix));
357
+ break;
358
+ case VDP_VIDEO_MIXER_ATTRIBUTE_BACKGROUND_COLOR:
359
+ case VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL:
360
+ case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA:
361
+ case VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA:
362
+ case VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL:
363
+ case VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE:
364
+ break;
365
+ default:
366
+ return VDP_STATUS_INVALID_VIDEO_MIXER_ATTRIBUTE;
367
+ }
368
+ }
369
370
- return VDP_STATUS_ERROR;
371
+ return VDP_STATUS_OK;
372
}
373
374
VdpStatus vdp_video_mixer_query_feature_support(VdpDevice device,
375
@@ -391,35 +499,45 @@ VdpStatus vdp_generate_csc_matrix(VdpProcamp *procamp,
376
VdpColorStandard standard,
377
VdpCSCMatrix *csc_matrix)
378
{
379
- if (!csc_matrix || !procamp)
380
+ if (!csc_matrix)
381
return VDP_STATUS_INVALID_POINTER;
382
383
- if (procamp->struct_version > VDP_PROCAMP_VERSION)
384
+ if (procamp && procamp->struct_version > VDP_PROCAMP_VERSION)
385
return VDP_STATUS_INVALID_STRUCT_VERSION;
386
387
- // BT.601 table
388
- (*csc_matrix)[0][1] = 0.000;
389
- (*csc_matrix)[0][2] = 1.403;
390
-
391
- (*csc_matrix)[1][1] = -0.344;
392
- (*csc_matrix)[1][2] = -0.714;
393
+ static const csc_m *cstd;
394
+ color_standard = standard;
395
+
396
+ switch (standard) {
397
+ case VDP_COLOR_STANDARD_ITUR_BT_709:
398
+ cstd = &cs_bt709;
399
+ break;
400
+ case VDP_COLOR_STANDARD_SMPTE_240M:
401
+ cstd = &cs_smpte_240m;
402
+ break;
403
+ case VDP_COLOR_STANDARD_ITUR_BT_601:
404
+ default:
405
+ cstd = &cs_bt601;
406
+ break;
407
+ }
408
409
- (*csc_matrix)[2][1] = 1.773;
410
- (*csc_matrix)[2][2] = 0.000;
411
+ float b = procamp ? procamp->brightness : 0.0f;
412
+ float c = procamp ? procamp->contrast : 1.0f;
413
+ float s = procamp ? procamp->saturation : 1.0f;
414
+ float h = procamp ? procamp->hue : 0.0f;
415
416
- float uvcos = procamp->saturation * cosf(procamp->hue);
417
- float uvsin = procamp->saturation * sinf(procamp->hue);
418
int i;
419
for (i = 0; i < 3; i++) {
420
- (*csc_matrix)[i][0] = procamp->contrast;
421
- float u = (*csc_matrix)[i][1] * uvcos + (*csc_matrix)[i][2] * uvsin;
422
- float v = (*csc_matrix)[i][1] * uvsin + (*csc_matrix)[i][2] * uvcos;
423
- (*csc_matrix)[i][1] = u;
424
- (*csc_matrix)[i][2] = v;
425
- (*csc_matrix)[i][3] = - (u + v) / 2;
426
- (*csc_matrix)[i][3] += 0.5 - procamp->contrast / 2;
427
- (*csc_matrix)[i][3] += procamp->brightness;
428
+ (*csc_matrix)[i][0] = c * (*cstd)[i][0];
429
+ (*csc_matrix)[i][1] = c * (*cstd)[i][1] * s * cosf(h) - c * (*cstd)[i][2] * s * sinf(h);
430
+ (*csc_matrix)[i][2] = c * (*cstd)[i][2] * s * cosf(h) + c * (*cstd)[i][1] * s * sinf(h);
431
+ (*csc_matrix)[i][3] = (*cstd)[i][3] + (*cstd)[i][0] * (b + c * ybias) +
432
+ (*cstd)[i][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) +
433
+ (*cstd)[i][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h));
434
}
435
+ VDPAU_DBG("Generate CSC matrix from following color standard: %d", standard);
436
+ VDPAU_DBG(">procamp->bright: %2.3f, procamp->contrast: %2.3f, procamp->saturation: %2.3f, procamp->hue: %2.3f",
437
+ (double)b, (double)c, (double)s, (double)h);
438
439
return VDP_STATUS_OK;
440
}
441
442