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