summaryrefslogtreecommitdiff
path: root/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'video.c')
-rw-r--r--video.c133
1 files changed, 108 insertions, 25 deletions
diff --git a/video.c b/video.c
index 169a50e..84574db 100644
--- a/video.c
+++ b/video.c
@@ -196,6 +196,17 @@ typedef enum _video_zoom_modes_
} VideoZoomModes;
///
+/// Video color space conversions.
+///
+typedef enum _video_color_space_
+{
+ VideoColorSpaceNone, ///< no conversion
+ VideoColorSpaceBt601, ///< ITU.BT-601 Y'CbCr
+ VideoColorSpaceBt709, ///< ITU.BT-709 HDTV Y'CbCr
+ VideoColorSpaceSmpte240 ///< SMPTE-240M Y'PbPr
+} VideoColorSpace;
+
+///
/// Video output module structure and typedef.
///
typedef struct _video_module_
@@ -291,7 +302,14 @@ static int VideoDenoise[VideoResolutionMax];
/// Default amount of of sharpening, or blurring, to apply (-1000 .. 1000).
static int VideoSharpen[VideoResolutionMax];
-// FIXME: color space / studio levels
+ /// Color space ITU-R BT.601, ITU-R BT.709, ...
+static const VideoColorSpace VideoColorSpaces[VideoResolutionMax] = {
+ VideoColorSpaceBt601, VideoColorSpaceBt709, VideoColorSpaceBt709,
+ VideoColorSpaceBt709
+};
+
+ /// Flag use studio levels
+static char VideoStudioLevels;
/// Default scaling mode
static VideoScalingModes VideoScaling[VideoResolutionMax];
@@ -1583,15 +1601,22 @@ static void VaapiInitSurfaceFlags(VaapiDecoder * decoder)
for (i = 0; i < VideoResolutionMax; ++i) {
decoder->SurfaceFlagsTable[i] = VA_CLEAR_DRAWABLE;
- // color space conversion none, ITU-R BT.601, ITU-R BT.709
- if (i > VideoResolution576i) {
- decoder->SurfaceFlagsTable[i] |= VA_SRC_BT709;
- } else {
- decoder->SurfaceFlagsTable[i] |= VA_SRC_BT601;
+ // color space conversion none, ITU-R BT.601, ITU-R BT.709, ...
+ switch (VideoColorSpaces[i]) {
+ case VideoColorSpaceNone:
+ break;
+ case VideoColorSpaceBt601:
+ decoder->SurfaceFlagsTable[i] |= VA_SRC_BT601;
+ break;
+ case VideoColorSpaceBt709:
+ decoder->SurfaceFlagsTable[i] |= VA_SRC_BT709;
+ break;
+ case VideoColorSpaceSmpte240:
+ decoder->SurfaceFlagsTable[i] |= VA_SRC_SMPTE_240;
+ break;
}
// scaling flags FAST, HQ, NL_ANAMORPHIC
- // FIXME: need to detect the backend to choose the parameter
switch (VideoScaling[i]) {
case VideoScalingNormal:
decoder->SurfaceFlagsTable[i] |= VA_FILTER_SCALING_DEFAULT;
@@ -1607,7 +1632,7 @@ static void VaapiInitSurfaceFlags(VaapiDecoder * decoder)
break;
case VideoScalingAnamorphic:
// intel backend supports only VA_FILTER_SCALING_NL_ANAMORPHIC;
- // don't use it, its for 4:3 -> 16:9 scaling
+ // FIXME: Highlevel should display 4:3 as 16:9 to support this
decoder->SurfaceFlagsTable[i] |=
VA_FILTER_SCALING_NL_ANAMORPHIC;
break;
@@ -5123,7 +5148,7 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
float noise_reduction_level;
float sharpness_level;
VdpColorStandard color_standard;
- VdpCSCMatrix csc_matrix[1];
+ VdpCSCMatrix csc_matrix;
//
// Build enables table
@@ -5218,26 +5243,80 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
attribute_value_ptrs[attribute_n++] = &sharpness_level;
Debug(3, "video/vdpau: sharpness level %+1.3f\n", sharpness_level);
}
- // FIXME: studio colors, VideoColorStandard[decoder->Resolution]
- if (decoder->InputWidth > 1280 || decoder->InputHeight > 576) {
- // HDTV
- color_standard = VDP_COLOR_STANDARD_ITUR_BT_709;
- Debug(3, "video/vdpau: color space ITU-R BT.709\n");
- } else {
- // SDTV
- color_standard = VDP_COLOR_STANDARD_ITUR_BT_601;
- Debug(3, "video/vdpau: color space ITU-R BT.601\n");
+ switch (VideoColorSpaces[decoder->Resolution]) {
+ case VideoColorSpaceNone:
+ default:
+ color_standard = 0;
+ break;
+ case VideoColorSpaceBt601:
+ color_standard = VDP_COLOR_STANDARD_ITUR_BT_601;
+ Debug(3, "video/vdpau: color space ITU-R BT.601\n");
+ break;
+ case VideoColorSpaceBt709:
+ color_standard = VDP_COLOR_STANDARD_ITUR_BT_709;
+ Debug(3, "video/vdpau: color space ITU-R BT.709\n");
+ break;
+ case VideoColorSpaceSmpte240:
+ color_standard = VDP_COLOR_STANDARD_SMPTE_240M;
+ Debug(3, "video/vdpau: color space SMPTE-240M\n");
+ break;
}
-
- status =
- VdpauGenerateCSCMatrix(&decoder->Procamp, color_standard, csc_matrix);
- if (status != VDP_STATUS_OK) {
- Error(_("video/vdpau: can't generate CSC matrix: %s\n"),
- VdpauGetErrorString(status));
+ //
+ // Studio levels
+ //
+ // based on www.nvnews.net forum thread
+ //
+ if (VideoStudioLevels) {
+ static const float color_coeffs[][3] = {
+ {0.299, 0.587, 0.114},
+ {0.2125, 0.7154, 0.0721},
+ {0.2122, 0.7013, 0.0865}
+ };
+ float uvcos, uvsin;
+ float uv_coeffs[3][2];
+ float Kr, Kg, Kb;
+ const int rgbmin = 16;
+ const int rgbr = 235 - rgbmin;
+
+ Kr = color_coeffs[color_standard][0];
+ Kg = color_coeffs[color_standard][1];
+ Kb = color_coeffs[color_standard][2];
+
+ uv_coeffs[0][0] = 0.0;
+ uv_coeffs[0][1] = (rgbr / 112.0) * (1.0 - Kr);
+ uv_coeffs[1][0] = -(rgbr / 112.0) * (1.0 - Kb) * Kb / Kg;
+ uv_coeffs[1][1] = -(rgbr / 112.0) * (1.0 - Kr) * Kr / Kg;
+ uv_coeffs[2][0] = (rgbr / 112.0) * (1.0 - Kb);
+ uv_coeffs[2][1] = 0.0;
+
+ uvcos = decoder->Procamp.saturation * cos(decoder->Procamp.hue);
+ uvsin = decoder->Procamp.saturation * sin(decoder->Procamp.hue);
+
+ for (i = 0; i < 3; ++i) {
+ csc_matrix[i][3] = decoder->Procamp.brightness;
+ csc_matrix[i][0] = rgbr * decoder->Procamp.contrast / 219;
+ csc_matrix[i][3] += (-16 / 255.0) * csc_matrix[i][0];
+ csc_matrix[i][1] =
+ uv_coeffs[i][0] * uvcos + uv_coeffs[i][1] * uvsin;
+ csc_matrix[i][3] += (-128 / 255.0) * csc_matrix[i][1];
+ csc_matrix[i][2] =
+ uv_coeffs[i][0] * uvsin + uv_coeffs[i][1] * uvcos;
+ csc_matrix[i][3] += (-128 / 255.0) * csc_matrix[i][2];
+ csc_matrix[i][3] += rgbmin / 255.0;
+ csc_matrix[i][3] += 0.5 - decoder->Procamp.contrast / 2.0;
+ }
+ } else {
+ status =
+ VdpauGenerateCSCMatrix(&decoder->Procamp, color_standard,
+ &csc_matrix);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't generate CSC matrix: %s\n"),
+ VdpauGetErrorString(status));
+ }
}
attributes[attribute_n] = VDP_VIDEO_MIXER_ATTRIBUTE_CSC_MATRIX;
- attribute_value_ptrs[attribute_n++] = csc_matrix;
+ attribute_value_ptrs[attribute_n++] = &csc_matrix;
status =
VdpauVideoMixerSetAttributeValues(decoder->VideoMixer, attribute_n,
@@ -9180,6 +9259,10 @@ void VideoInit(const char *display_name)
if (getenv("NO_HW")) {
VideoHardwareDecoder = 0;
}
+ VideoStudioLevels = 0;
+ if (getenv("STUDIO_LEVELS")) {
+ VideoStudioLevels = 1;
+ }
//xcb_prefetch_maximum_request_length(Connection);
xcb_flush(Connection);
}