From f28a737a9a5161257e15bc146ff0ffe77af00a27 Mon Sep 17 00:00:00 2001 From: Johns Date: Fri, 10 Feb 2012 15:47:52 +0100 Subject: [PATCH] VDPAU: support for studio levels added. --- ChangeLog | 1 + Todo | 4 +- video.c | 131 ++++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 111 insertions(+), 25 deletions(-) diff --git a/ChangeLog b/ChangeLog index 4dce0eb..c2aeb06 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,7 @@ User johns Date: + VDPAU: support for studio levels added. Add support for skip chroma deinterlace to software deinterlacer. Type of software deinterlacer now configurable from setup menu. Mixer channel could be set through command line option. diff --git a/Todo b/Todo index 120d928..e1a0bdc 100644 --- a/Todo +++ b/Todo @@ -21,10 +21,10 @@ $Id: $ missing: software deinterlace (yadif, ...) software decoder with software deinterlace - ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)? suspend output / energie saver: stop and restart X11 suspend plugin didn't restore full-screen (is this wanted?) Option deinterlace off / deinterlace force! + ColorSpace and StudioLevels aren't configurable with the gui. crash: AudioPlayHandlerThread -> pthread_cond_wait @@ -85,6 +85,8 @@ audio: add pause support for replay pause some plugin send a private LPCM stream (CODEC_ID_PCM_DVD), which isn't supported by ffmpeg, write own parser. + Mute should do a real mute and not only set volume to zero. + Starting suspended and muted, didn't register the mute. audio/alsa: better downmix of >2 channels on 2 channel hardware diff --git a/video.c b/video.c index 169a50e..84574db 100644 --- a/video.c +++ b/video.c @@ -195,6 +195,17 @@ typedef enum _video_zoom_modes_ VideoAnamorphic, ///< anamorphic scaled (unsupported) } 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. /// @@ -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; } + // + // 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; - 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)); + 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); }