summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2012-01-05 17:20:44 +0100
committerJohns <johns98@gmx.net>2012-01-05 17:20:44 +0100
commit0776bc5ee472f5013e2507ecb088673e9152caee (patch)
tree4c07baa0c35e60e3f36687c978779022743169a0
parentaba14813c008c4d5a7577e4191be686ab8bf4cc4 (diff)
downloadvdr-plugin-softhddevice-0776bc5ee472f5013e2507ecb088673e9152caee.tar.gz
vdr-plugin-softhddevice-0776bc5ee472f5013e2507ecb088673e9152caee.tar.bz2
VDPAU improvements.
Add denoise, sharpness, skip chroma deinterlace support. Show OSD only if something is to display, improves performance. Add deinterlace mode with only 4 surfaces.
-rw-r--r--ChangeLog9
-rw-r--r--README.txt14
-rw-r--r--Todo8
-rw-r--r--softhddevice.cpp75
-rw-r--r--video.c385
-rw-r--r--video.h11
6 files changed, 385 insertions, 117 deletions
diff --git a/ChangeLog b/ChangeLog
index 2923fcb..523d0e7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
User johns
-Date:
+Data:
+
+ VDPAU: Add denoise and sharpness support.
+ VDPAU: Add skip chroma deinterlace support.
+ VDPAU: Show OSD only if something is to display, improves performance.
+ VDPAU: Add deinterlace with only 4 surfaces.
+
+Date: Thu Jan 4 17:00:00 CET 2012
Release Version 0.1.5
Adds OSS mixer support.
diff --git a/README.txt b/README.txt
index 7c06269..f50bc17 100644
--- a/README.txt
+++ b/README.txt
@@ -92,12 +92,22 @@ Setup: /etc/vdr/setup.conf
------
Following is supported:
+ softhddevice.MakePrimary = 1
+ 0 = no change, 1 make softhddevice primary at start
+
softhddevice.Deinterlace = 0
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
(only 0, 1 supported with vaapi)
- softhddevice.MakePrimary = 1
- 0 = no change, 1 make softhddevice primary at start
+ softhddevice.SkipChromaDeinterlace = 0
+ 0 = disabled, 1 = enabled (for slower cards, poor qualität)
+
+ softhddevice.Denoise = 0
+ 0 .. 1000 noise reduction level (0 off, 1000 max)
+
+ softhddevice.Sharpness = 0
+ -1000 .. 1000 noise reduction level (0 off, -1000 max blur,
+ 1000 max sharp)
softhddevice.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
diff --git a/Todo b/Todo
index e6570b0..548f00d 100644
--- a/Todo
+++ b/Todo
@@ -30,11 +30,18 @@ missing:
HDMI/SPDIF Passthrough
disable screensaver
disable window cursor
+ ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)?
vdpau:
1080i with temporal spatial and level 1 scaling too slow with GT 520
1080i with temporal spatial too slow with GT 520 on some channels
+ SkipChromaDeinterlace improves performance
+ Improve OSD handling, show only what is used. Big OSD costs performance
VdpPreemptionCallback handling
+ hard channel switch
+
+libva:
+ hard channel switch
libva-intel-driver:
intel still has hangups most with 1080i
@@ -73,6 +80,7 @@ audio/oss:
playback of recording
play back is too fast
+ pause is not reset, when replay exit
setup:
Setup of decoder type.
diff --git a/softhddevice.cpp b/softhddevice.cpp
index 97cb12a..a501409 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -49,11 +49,14 @@ static class cSoftHdDevice *MyDevice;
//////////////////////////////////////////////////////////////////////////////
-static char ConfigMakePrimary; ///< config primary wanted
-static char ConfigVideoDeinterlace; ///< config deinterlace
-static char ConfigVideoScaling; ///< config scaling
-static int ConfigVideoAudioDelay; ///< config audio delay
-static char DoMakePrimary; ///< flag switch primary
+static char ConfigMakePrimary; ///< config primary wanted
+static char ConfigVideoDeinterlace; ///< config deinterlace
+static char ConfigVideoSkipChromaDeinterlace; ///< config skip chroma
+static int ConfigVideoDenoise; ///< config denoise
+static int ConfigVideoSharpen; ///< config sharpen
+static char ConfigVideoScaling; ///< config scaling
+static int ConfigVideoAudioDelay; ///< config audio delay
+static char DoMakePrimary; ///< flag switch primary
//////////////////////////////////////////////////////////////////////////////
@@ -226,7 +229,7 @@ class cSoftOsdProvider:public cOsdProvider
cSoftOsdProvider(void);
};
-cOsd *cSoftOsdProvider::Osd; ///< single osd
+cOsd *cSoftOsdProvider::Osd; ///< single osd
/**
** Create a new OSD.
@@ -262,6 +265,9 @@ class cMenuSetupSoft:public cMenuSetupPage
protected:
int MakePrimary;
int Deinterlace;
+ int SkipChromaDeinterlace;
+ int Denoise;
+ int Sharpen;
int Scaling;
int AudioDelay;
protected:
@@ -275,10 +281,12 @@ class cMenuSetupSoft:public cMenuSetupPage
*/
cMenuSetupSoft::cMenuSetupSoft(void)
{
- static const char * const deinterlace[] = {
- "Bob", "Weave", "Temporal", "TemporalSpatial", "Software" };
- static const char * const scaling[] = {
- "Normal", "Fast", "HQ", "Anamorphic" };
+ static const char *const deinterlace[] = {
+ "Bob", "Weave", "Temporal", "TemporalSpatial", "Software"
+ };
+ static const char *const scaling[] = {
+ "Normal", "Fast", "HQ", "Anamorphic"
+ };
// cMenuEditBoolItem cMenuEditBitItem cMenuEditNumItem
// cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem
@@ -286,11 +294,22 @@ cMenuSetupSoft::cMenuSetupSoft(void)
Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary,
tr("no"), tr("yes")));
Deinterlace = ConfigVideoDeinterlace;
- Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace, 5, deinterlace));
+ Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace, 5,
+ deinterlace));
+ SkipChromaDeinterlace = ConfigVideoSkipChromaDeinterlace;
+ Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"),
+ &SkipChromaDeinterlace, tr("no"), tr("yes")));
+ Denoise = ConfigVideoDenoise;
+ Add(new cMenuEditIntItem(tr("Denoise (vdpau 0..1000)"), &Denoise, 0,
+ 1000));
+ Sharpen = ConfigVideoSharpen;
+ Add(new cMenuEditIntItem(tr("Sharpen (vdpau -1000..1000)"), &Sharpen,
+ -1000, 1000));
Scaling = ConfigVideoScaling;
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling, 4, scaling));
AudioDelay = ConfigVideoAudioDelay;
- Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000, 1000));
+ Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000,
+ 1000));
}
/**
@@ -301,6 +320,13 @@ void cMenuSetupSoft::Store(void)
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
SetupStore("Deinterlace", ConfigVideoDeinterlace = Deinterlace);
VideoSetDeinterlace(ConfigVideoDeinterlace);
+ SetupStore("SkipChromaDeinterlace", ConfigVideoSkipChromaDeinterlace =
+ SkipChromaDeinterlace);
+ VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
+ SetupStore("Denoise", ConfigVideoDenoise = Denoise);
+ VideoSetDenoise(ConfigVideoDenoise);
+ SetupStore("Sharpen", ConfigVideoSharpen = Sharpen);
+ VideoSetSharpen(ConfigVideoSharpen);
SetupStore("Scaling", ConfigVideoScaling = Scaling);
VideoSetScaling(ConfigVideoScaling);
SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
@@ -333,7 +359,7 @@ class cSoftHdDevice:public cDevice
virtual void GetOsdSize(int &, int &, double &);
virtual int PlayVideo(const uchar *, int);
//virtual int PlayTsVideo(const uchar *, int);
-#ifdef USE_OSS // FIXME: testing only oss
+#ifdef USE_OSS // FIXME: testing only oss
virtual int PlayTsAudio(const uchar *, int);
#endif
virtual void SetAudioChannelDevice(int);
@@ -436,7 +462,7 @@ int64_t cSoftHdDevice::GetSTC(void)
{
// dsyslog("[softhddev]%s:\n", __FUNCTION__);
- return ::VideoGetClock();
+ return::VideoGetClock();
}
void cSoftHdDevice::TrickSpeed(int Speed)
@@ -496,7 +522,7 @@ bool cSoftHdDevice::Poll(
{
// dsyslog("[softhddev]%s: %d\n", __FUNCTION__, timeout_ms);
- return ::Poll(timeout_ms);
+ return::Poll(timeout_ms);
}
bool cSoftHdDevice::Flush(int timeout_ms)
@@ -560,7 +586,7 @@ int cSoftHdDevice::PlayVideo(const uchar * data, int length)
{
//dsyslog("[softhddev]%s: %p %d\n", __FUNCTION__, data, length);
- return ::PlayVideo(data, length);
+ return::PlayVideo(data, length);
}
#if 0
@@ -573,7 +599,7 @@ int cSoftHdDevice::PlayTsVideo(const uchar * Data, int Length)
}
#endif
-#ifdef USE_OSS // FIXME: testing only oss
+#ifdef USE_OSS // FIXME: testing only oss
///
/// Play a TS audio packet.
///
@@ -583,7 +609,7 @@ int cSoftHdDevice::PlayTsAudio(const uchar * data, int length)
{
AudioPoller();
- return cDevice::PlayTsAudio(data,length);
+ return cDevice::PlayTsAudio(data, length);
}
#endif
@@ -786,6 +812,19 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
VideoSetDeinterlace(ConfigVideoDeinterlace = atoi(value));
return true;
}
+ if (!strcmp(name, "SkipChromaDeinterlace")) {
+ VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace =
+ atoi(value));
+ return true;
+ }
+ if (!strcmp(name, "Denoise")) {
+ VideoSetDenoise(ConfigVideoDenoise = atoi(value));
+ return true;
+ }
+ if (!strcmp(name, "Sharpen")) {
+ VideoSetSharpen(ConfigVideoSharpen = atoi(value));
+ return true;
+ }
if (!strcmp(name, "Scaling")) {
VideoSetScaling(ConfigVideoScaling = atoi(value));
return true;
diff --git a/video.c b/video.c
index b6d031c..15336b4 100644
--- a/video.c
+++ b/video.c
@@ -1,7 +1,7 @@
///
/// @file video.c @brief Video module
///
-/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved.
+/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -37,6 +37,7 @@
///
#define USE_XLIB_XCB
+#define noUSE_GRAB
#define noUSE_GLX
#define noUSE_DOUBLEBUFFER
@@ -197,6 +198,20 @@ static unsigned VideoWindowHeight; ///< video output window height
/// Default deinterlace mode
static VideoDeinterlaceModes VideoDeinterlace;
+ /// Default number of deinterlace surfaces
+static const int VideoDeinterlaceSurfaces = 4;
+
+ /// Default skip chroma deinterlace flag (VDPAU only)
+static int VideoSkipChromaDeinterlace = 1;
+
+ /// Default amount of noise reduction algorithm to apply (0 .. 1000).
+static int VideoDenoise;
+
+ /// Default amount of of sharpening, or blurring, to apply (-1000 .. 1000).
+static int VideoSharpen;
+
+// FIXME: color space
+
/// Default scaling mode
static VideoScalingModes VideoScaling;
@@ -3135,6 +3150,7 @@ static int VdpauTemporal; ///< temporal deinterlacer supported
static int VdpauTemporalSpatial; ///< temporal spatial deint. supported
static int VdpauInverseTelecine; ///< inverse telecine deint. supported
static int VdpauNoiseReduction; ///< noise reduction supported
+static int VdpauSharpness; ///< sharpness supported
static int VdpauSkipChroma; ///< skip chroma deint. supported
/// display surface ring buffer
@@ -3143,6 +3159,7 @@ static int VdpauSurfaceIndex; ///< current display surface
static int VdpauOsdWidth; ///< width of osd surface
static int VdpauOsdHeight; ///< height of osd surface
+static int VdpauShowOsd; ///< flag show osd
#ifdef USE_BITMAP
/// bitmap surfaces for osd
@@ -3165,13 +3182,12 @@ static VdpGetErrorString *VdpauGetErrorString;
static VdpDeviceDestroy *VdpauDeviceDestroy;
static VdpGenerateCSCMatrix *VdpauGenerateCSCMatrix;
static VdpVideoSurfaceQueryCapabilities *VdpauVideoSurfaceQueryCapabilities;
-static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities
- *VdpauVideoSurfaceQueryGetPutBitsYCbCrCapabilities;
+static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *
+ VdpauVideoSurfaceQueryGetPutBitsYCbCrCapabilities;
static VdpVideoSurfaceCreate *VdpauVideoSurfaceCreate;
static VdpVideoSurfaceDestroy *VdpauVideoSurfaceDestroy;
static VdpVideoSurfaceGetParameters *VdpauVideoSurfaceGetParameters;
-
-//static VdpVideoSurfaceGetBitsYCbCr * VdpauVideoSurfaceGetBitsYCbCr;
+static VdpVideoSurfaceGetBitsYCbCr *VdpauVideoSurfaceGetBitsYCbCr;
static VdpVideoSurfacePutBitsYCbCr *VdpauVideoSurfacePutBitsYCbCr;
static VdpOutputSurfaceCreate *VdpauOutputSurfaceCreate;
@@ -3185,10 +3201,10 @@ static VdpBitmapSurfaceDestroy *VdpauBitmapSurfaceDestroy;
static VdpBitmapSurfacePutBitsNative *VdpauBitmapSurfacePutBitsNative;
-static VdpOutputSurfaceRenderOutputSurface *
- VdpauOutputSurfaceRenderOutputSurface;
-static VdpOutputSurfaceRenderBitmapSurface *
- VdpauOutputSurfaceRenderBitmapSurface;
+static VdpOutputSurfaceRenderOutputSurface
+ *VdpauOutputSurfaceRenderOutputSurface;
+static VdpOutputSurfaceRenderBitmapSurface
+ *VdpauOutputSurfaceRenderBitmapSurface;
static VdpDecoderQueryCapabilities *VdpauDecoderQueryCapabilities;
static VdpDecoderCreate *VdpauDecoderCreate;
@@ -3197,6 +3213,9 @@ static VdpDecoderDestroy *VdpauDecoderDestroy;
static VdpDecoderRender *VdpauDecoderRender;
static VdpVideoMixerQueryFeatureSupport *VdpauVideoMixerQueryFeatureSupport;
+static VdpVideoMixerQueryAttributeSupport
+ *VdpauVideoMixerQueryAttributeSupport;
+
static VdpVideoMixerCreate *VdpauVideoMixerCreate;
static VdpVideoMixerSetFeatureEnables *VdpauVideoMixerSetFeatureEnables;
static VdpVideoMixerSetAttributeValues *VdpauVideoMixerSetAttributeValues;
@@ -3206,18 +3225,18 @@ static VdpVideoMixerRender *VdpauVideoMixerRender;
static VdpPresentationQueueTargetDestroy *VdpauPresentationQueueTargetDestroy;
static VdpPresentationQueueCreate *VdpauPresentationQueueCreate;
static VdpPresentationQueueDestroy *VdpauPresentationQueueDestroy;
-static VdpPresentationQueueSetBackgroundColor
- *VdpauPresentationQueueSetBackgroundColor;
+static VdpPresentationQueueSetBackgroundColor *
+ VdpauPresentationQueueSetBackgroundColor;
static VdpPresentationQueueGetTime *VdpauPresentationQueueGetTime;
static VdpPresentationQueueDisplay *VdpauPresentationQueueDisplay;
-static VdpPresentationQueueBlockUntilSurfaceIdle *
- VdpauPresentationQueueBlockUntilSurfaceIdle;
-static VdpPresentationQueueQuerySurfaceStatus *
- VdpauPresentationQueueQuerySurfaceStatus;
+static VdpPresentationQueueBlockUntilSurfaceIdle
+ *VdpauPresentationQueueBlockUntilSurfaceIdle;
+static VdpPresentationQueueQuerySurfaceStatus
+ *VdpauPresentationQueueQuerySurfaceStatus;
-static VdpPresentationQueueTargetCreateX11
- *VdpauPresentationQueueTargetCreateX11;
+static VdpPresentationQueueTargetCreateX11 *
+ VdpauPresentationQueueTargetCreateX11;
///@}
///
@@ -3374,16 +3393,25 @@ static void VdpauPrintFrames(const VdpauDecoder * decoder)
///
/// @param decoder VDPAU hw decoder
///
+/// @note don't forget to update features, paramaters, attributes table
+/// size, if more is add.
+///
static void VdpauMixerSetup(VdpauDecoder * decoder)
{
VdpStatus status;
int i;
- VdpVideoMixerFeature features[14];
- VdpBool enables[14];
+ VdpVideoMixerFeature features[15];
+ VdpBool enables[15];
int feature_n;
- VdpVideoMixerParameter paramaters[10];
- void const *values[10];
+ VdpVideoMixerParameter paramaters[4];
+ void const *value_ptrs[4];
int parameter_n;
+ VdpVideoMixerAttribute attributes[3];
+ void const *attribute_value_ptrs[3];
+ int attribute_n;
+ uint8_t skip_chroma_value;
+ float noise_reduction_level;
+ float sharpness_level;
VdpChromaType chroma_type;
int layers;
@@ -3404,7 +3432,9 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
if (VdpauNoiseReduction) {
features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION;
}
- // VDP_VIDEO_MIXER_FEATURE_SHARPNESS
+ if (VdpauSharpness) {
+ features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS;
+ }
for (i = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1;
i <= VdpauHqScalingMax; ++i) {
features[feature_n++] = i;
@@ -3417,19 +3447,19 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
// Setup parameter/value tables
//
paramaters[0] = VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH;
- values[0] = &decoder->InputWidth;
+ value_ptrs[0] = &decoder->InputWidth;
paramaters[1] = VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT;
- values[1] = &decoder->InputHeight;
+ value_ptrs[1] = &decoder->InputHeight;
paramaters[2] = VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE;
- values[2] = &chroma_type;
+ value_ptrs[2] = &chroma_type;
layers = 0;
paramaters[3] = VDP_VIDEO_MIXER_PARAMETER_LAYERS;
- values[3] = &layers;
+ value_ptrs[3] = &layers;
parameter_n = 4;
status =
VdpauVideoMixerCreate(VdpauDevice, feature_n, features, parameter_n,
- paramaters, values, &decoder->VideoMixer);
+ paramaters, value_ptrs, &decoder->VideoMixer);
if (status != VDP_STATUS_OK) {
Fatal(_("video/vdpau: can't create video mixer: %s\n"),
VdpauGetErrorString(status));
@@ -3441,8 +3471,8 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
feature_n = 0;
if (VdpauTemporal) {
enables[feature_n] = (VideoDeinterlace == VideoDeinterlaceTemporal
- || VideoDeinterlace ==
- VideoDeinterlaceTemporalSpatial) ? VDP_TRUE : VDP_FALSE;
+ || (VideoDeinterlace == VideoDeinterlaceTemporalSpatial
+ && !VdpauTemporalSpatial)) ? VDP_TRUE : VDP_FALSE;
features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL;
Debug(3, "video/vdpau: temporal deinterlace %s\n",
enables[feature_n - 1] ? "enabled" : "disabled");
@@ -3463,11 +3493,17 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
enables[feature_n - 1] ? "enabled" : "disabled");
}
if (VdpauNoiseReduction) {
- enables[feature_n] = VDP_FALSE;
- features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_INVERSE_TELECINE;
+ enables[feature_n] = VideoDenoise ? VDP_TRUE : VDP_FALSE;
+ features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION;
Debug(3, "video/vdpau: noise reduction %s\n",
enables[feature_n - 1] ? "enabled" : "disabled");
}
+ if (VdpauSharpness) {
+ enables[feature_n] = VideoSharpen ? VDP_TRUE : VDP_FALSE;
+ features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS;
+ Debug(3, "video/vdpau: sharpness %s\n",
+ enables[feature_n - 1] ? "enabled" : "disabled");
+ }
for (i = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1;
i <= VdpauHqScalingMax; ++i) {
enables[feature_n] =
@@ -3486,10 +3522,34 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL
VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MIN_LUMA
VDP_VIDEO_MIXER_ATTRIBUTE_LUMA_KEY_MAX_LUMA
- VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE
- VdpVideoMixerSetAttributeValues(decoder->Mixer, attribute_n,
- attributes, values);
*/
+ attribute_n = 0;
+ if (VdpauSkipChroma) {
+ skip_chroma_value = VideoSkipChromaDeinterlace;
+ attributes[attribute_n]
+ = VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE;
+ attribute_value_ptrs[attribute_n++] = &skip_chroma_value;
+ Debug(3, "video/vdpau: skip chroma deinterlace %s\n",
+ skip_chroma_value ? "enabled" : "disabled");
+ }
+ if (VdpauNoiseReduction) {
+ noise_reduction_level = VideoDenoise / 1000.0;
+ attributes[attribute_n]
+ = VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL;
+ attribute_value_ptrs[attribute_n++] = &noise_reduction_level;
+ Debug(3, "video/vdpau: noise reduction level %1.3f\n",
+ noise_reduction_level);
+ }
+ if (VdpauSharpness) {
+ sharpness_level = VideoSharpen / 1000.0;
+ attributes[attribute_n]
+ = VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL;
+ attribute_value_ptrs[attribute_n++] = &sharpness_level;
+ Debug(3, "video/vdpau: sharpness level %+1.3f\n", sharpness_level);
+ }
+
+ VdpauVideoMixerSetAttributeValues(decoder->VideoMixer, attribute_n,
+ attributes, attribute_value_ptrs);
//VdpColorStandard color_standard;
//color_standard = VDP_COLOR_STANDARD_ITUR_BT_601;
@@ -3711,7 +3771,8 @@ static void VideoVdpauInit(const char *display_name)
"VideoSurfaceDestroy");
VdpauGetProc(VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS,
&VdpauVideoSurfaceGetParameters, "VideoSurfaceGetParameters");
- // VdpauGetProc(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, &VdpauVideoSurfaceGetBitsYCbCr, "VideoSurfaceGetBitsYCbCr");
+ VdpauGetProc(VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR,
+ &VdpauVideoSurfaceGetBitsYCbCr, "VideoSurfaceGetBitsYCbCr");
VdpauGetProc(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR,
&VdpauVideoSurfacePutBitsYCbCr, "VideoSurfacePutBitsYCbCr");
#if 0
@@ -3775,7 +3836,11 @@ static void VideoVdpauInit(const char *display_name)
&VdpauVideoMixerQueryFeatureSupport, "VideoMixerQueryFeatureSupport");
#if 0
VdpauGetProc(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_SUPPORT, &, "");
- VdpauGetProc(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT, &, "");
+#endif
+ VdpauGetProc(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_SUPPORT,
+ &VdpauVideoMixerQueryAttributeSupport,
+ "VideoMixerQueryAttributeSupport");
+#if 0
VdpauGetProc(VDP_FUNC_ID_VIDEO_MIXER_QUERY_PARAMETER_VALUE_RANGE, &, "");
VdpauGetProc(VDP_FUNC_ID_VIDEO_MIXER_QUERY_ATTRIBUTE_VALUE_RANGE, &, "");
#endif
@@ -3921,6 +3986,16 @@ static void VideoVdpauInit(const char *display_name)
status =
VdpauVideoMixerQueryFeatureSupport(VdpauDevice,
+ VDP_VIDEO_MIXER_FEATURE_SHARPNESS, &flag);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't query feature '%s': %s\n"), "sharpness",
+ VdpauGetErrorString(status));
+ } else {
+ VdpauSharpness = flag;
+ }
+
+ status =
+ VdpauVideoMixerQueryAttributeSupport(VdpauDevice,
VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE, &flag);
if (status != VDP_STATUS_OK) {
Error(_("video/vdpau: can't query feature '%s': %s\n"),
@@ -3937,9 +4012,9 @@ static void VideoVdpauInit(const char *display_name)
Info(_("video/vdpau: feature deinterlace temporal %s\n"),
VdpauTemporal ? _("supported") : _("unsupported"));
Info(_("video/vdpau: feature deinterlace temporal spatial %s\n"),
- VdpauTemporal ? _("supported") : _("unsupported"));
+ VdpauTemporalSpatial ? _("supported") : _("unsupported"));
Info(_("video/vdpau: attribute skip chroma deinterlace %s\n"),
- VdpauTemporal ? _("supported") : _("unsupported"));
+ VdpauSkipChroma ? _("supported") : _("unsupported"));
//
// video formats
@@ -4338,6 +4413,69 @@ static void VdpauSetup(VdpauDecoder * decoder,
}
///
+/// Grab video surface.
+///
+/// @param decoder VDPAU hw decoder
+///
+static void VdpauGrabSurface(VdpauDecoder * decoder)
+{
+ VdpVideoSurface surface;
+ VdpStatus status;
+ VdpChromaType chroma_type;
+ uint32_t size;
+ uint32_t width;
+ uint32_t height;
+ void *base;
+ void *data[3];
+ uint32_t pitches[3];
+ VdpYCbCrFormat format;
+
+ // FIXME: test function to grab output surface content
+ // for screen shots, atom light and auto crop.
+
+ surface = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
+ % VIDEO_SURFACES_MAX];
+
+ // get real surface size
+ status =
+ VdpauVideoSurfaceGetParameters(surface, &chroma_type, &width, &height);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't get video surface parameters: %s\n"),
+ VdpauGetErrorString(status));
+ return;
+ }
+ switch (chroma_type) {
+ case VDP_CHROMA_TYPE_420:
+ case VDP_CHROMA_TYPE_422:
+ case VDP_CHROMA_TYPE_444:
+ size = width * height + ((width + 1) / 2) * ((height + 1) / 2)
+ + ((width + 1) / 2) * ((height + 1) / 2);
+ base = malloc(size);
+ if (!base) {
+ Error(_("video/vdpau: out of memory\n"));
+ return;
+ }
+ pitches[0] = width;
+ pitches[1] = width / 2;
+ pitches[2] = width / 2;
+ data[0] = base;
+ data[1] = base + width * height;
+ data[2] = base + width * height + width * height / 4;
+ format = VDP_YCBCR_FORMAT_YV12;
+ break;
+ }
+ status = VdpauVideoSurfaceGetBitsYCbCr(surface, format, data, pitches);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't get video surface bits: %s\n"),
+ VdpauGetErrorString(status));
+ return;
+ }
+ // 0x10 0x80 0x80 black
+
+ free(base);
+}
+
+///
/// Queue output surface.
///
/// @param decoder VDPAU hw decoder
@@ -4562,8 +4700,9 @@ static void VdpauMixOsd(void)
VdpRect source_rect;
VdpRect output_rect;
VdpStatus status;
- uint32_t start;
- uint32_t end;
+
+ //uint32_t start;
+ //uint32_t end;
//
// blend overlay over output
@@ -4592,7 +4731,7 @@ static void VdpauMixOsd(void)
output_rect.x1 = VideoWindowWidth;
output_rect.y1 = VideoWindowHeight;
- start = GetMsTicks();
+ //start = GetMsTicks();
VdpauOsdSurfaceIndex = 1;
#ifdef USE_BITMAP
@@ -4616,7 +4755,7 @@ static void VdpauMixOsd(void)
VdpauGetErrorString(status));
}
#endif
- end = GetMsTicks();
+ //end = GetMsTicks();
//Debug(3, "video:/vdpau: osd render %d ms\n", end - start);
@@ -4651,56 +4790,99 @@ static void VdpauMixVideo(VdpauDecoder * decoder)
dst_video_rect.x1 = decoder->OutputX + decoder->OutputWidth;
dst_video_rect.y1 = decoder->OutputY + decoder->OutputHeight;
+#ifdef USE_GRAB
+ VdpauGrabSurface(decoder);
+#endif
+
if (decoder->Interlaced && VideoDeinterlace != VideoDeinterlaceWeave) {
//
// Build deinterlace structures
//
VdpVideoMixerPictureStructure cps;
- VdpVideoSurface past[2];
- VdpVideoSurface future[2];
+ VdpVideoSurface past[3];
+ int past_n;
+ VdpVideoSurface future[3];
+ int future_n;
#ifdef DEBUG
if (atomic_read(&decoder->SurfacesFilled) < 3) {
Debug(3, "only %d\n", atomic_read(&decoder->SurfacesFilled));
}
#endif
+ // FIXME: can use VDP_INVALID_HANDLE to support less surface on start
- // FIXME: wrong for bottom-field first
- // read: past: B0 T0 current T1 future B1 T2 (0 1 2)
- // read: past: T1 B0 current B1 future T2 B2 (0 1 2)
- if (decoder->TopFieldFirst != decoder->SurfaceField) {
- cps = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
+ if (VideoDeinterlaceSurfaces == 5) {
+ past_n = 2;
+ future_n = 2;
- past[1] = decoder->SurfacesRb[decoder->SurfaceRead];
- past[0] = past[1];
- current = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
- % VIDEO_SURFACES_MAX];
- future[0] = current;
- future[1] = decoder->SurfacesRb[(decoder->SurfaceRead + 2)
- % VIDEO_SURFACES_MAX];
- // FIXME: can support 1 future more
- } else {
- cps = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
+ // FIXME: wrong for bottom-field first
+ // read: past: B0 T0 current T1 future B1 T2 (0 1 2)
+ // read: past: T1 B0 current B1 future T2 B2 (0 1 2)
+ if (decoder->TopFieldFirst != decoder->SurfaceField) {
+ cps = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
+
+ past[1] = decoder->SurfacesRb[decoder->SurfaceRead];
+ past[0] = past[1];
+ current = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
+ % VIDEO_SURFACES_MAX];
+ future[0] = current;
+ future[1] = decoder->SurfacesRb[(decoder->SurfaceRead + 2)
+ % VIDEO_SURFACES_MAX];
+ // FIXME: can support 1 future more
+ } else {
+ cps = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
+
+ // FIXME: can support 1 past more
+ past[1] = decoder->SurfacesRb[decoder->SurfaceRead];
+ past[0] = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
+ % VIDEO_SURFACES_MAX];
+ current = past[0];
+ future[0] = decoder->SurfacesRb[(decoder->SurfaceRead + 2)
+ % VIDEO_SURFACES_MAX];
+ future[1] = future[0];
+ }
- // FIXME: can support 1 past more
- past[1] = decoder->SurfacesRb[decoder->SurfaceRead];
- past[0] = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
- % VIDEO_SURFACES_MAX];
- current = past[0];
- future[0] = decoder->SurfacesRb[(decoder->SurfaceRead + 2)
- % VIDEO_SURFACES_MAX];
- future[1] = future[0];
+ } else if (VideoDeinterlaceSurfaces == 4) {
+ past_n = 2;
+ future_n = 1;
+
+ // FIXME: wrong for bottom-field first
+ // read: past: B0 T0 current T1 future B1 (0 1 2)
+ // read: past: T1 B0 current B1 future T2 (0 1 2)
+ if (decoder->TopFieldFirst != decoder->SurfaceField) {
+ cps = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;
+
+ past[1] = decoder->SurfacesRb[decoder->SurfaceRead];
+ past[0] = past[1];
+ current = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
+ % VIDEO_SURFACES_MAX];
+ future[0] = current;
+ } else {
+ cps = VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD;
+
+ past[1] = decoder->SurfacesRb[decoder->SurfaceRead];
+ past[0] = decoder->SurfacesRb[(decoder->SurfaceRead + 1)
+ % VIDEO_SURFACES_MAX];
+ current = past[0];
+ future[0] = decoder->SurfacesRb[(decoder->SurfaceRead + 2)
+ % VIDEO_SURFACES_MAX];
+ }
+
+ } else {
+ Error(_("video/vdpau: %d surface deinterlace unsupported\n"),
+ VideoDeinterlaceSurfaces);
}
+ // FIXME: past_n, future_n here:
Debug(4, " %02d %02d(%c%02d) %02d %02d\n", past[1], past[0],
cps == VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD ? 'T' : 'B',
current, future[0], future[1]);
status =
VdpauVideoMixerRender(decoder->VideoMixer, VDP_INVALID_HANDLE,
- NULL, cps, 2, past, current, 2, future, &video_src_rect,
- VdpauSurfacesRb[VdpauSurfaceIndex], &dst_rect, &dst_video_rect, 0,
- NULL);
+ NULL, cps, past_n, past, current, future_n, future,
+ &video_src_rect, VdpauSurfacesRb[VdpauSurfaceIndex], &dst_rect,
+ &dst_video_rect, 0, NULL);
} else {
current = decoder->SurfacesRb[decoder->SurfaceRead];
@@ -4804,32 +4986,25 @@ static void VdpauAdvanceFrame(void)
///
static void VdpauDisplayFrame(void)
{
- uint32_t now;
- uint32_t end;
- static uint32_t last_frame_tick;
VdpStatus status;
VdpTime first_time;
static VdpTime last_time;
int i;
- now = GetMsTicks();
- Debug(4, "video/vdpau: tick %d\n", now - last_frame_tick);
-
//
// wait for surface visible (blocks max ~5ms)
//
status =
VdpauPresentationQueueBlockUntilSurfaceIdle(VdpauQueue,
VdpauSurfacesRb[VdpauSurfaceIndex], &first_time);
- end = GetMsTicks();
if (status != VDP_STATUS_OK) {
Error(_("video/vdpau: can't block queue: %s\n"),
VdpauGetErrorString(status));
}
// check if surface was displayed for more than 1 frame
if (last_time && first_time > last_time + 21 * 1000 * 1000) {
- Debug(3, "video/vdpau: %ld display time %ld - %d ms\n", first_time,
- (first_time - last_time) / 1000, end - now);
+ Debug(3, "video/vdpau: %ld display time %ld\n", first_time / 1000,
+ (first_time - last_time) / 1000);
// FIXME: can be more than 1 frame long shown
for (i = 0; i < VdpauDecoderN; ++i) {
VdpauDecoders[i]->FramesMissed++;
@@ -4842,7 +5017,6 @@ static void VdpauDisplayFrame(void)
}
}
last_time = first_time;
- last_frame_tick = now;
//
// Render videos into output
@@ -4868,8 +5042,9 @@ static void VdpauDisplayFrame(void)
//
// add osd to surface
//
- VdpauMixOsd();
-
+ if (VdpauShowOsd) { // showing costs performance
+ VdpauMixOsd();
+ }
//
// place surface in presentation queue
//
@@ -4906,17 +5081,6 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
VdpauAdvanceFrame();
}
filled = atomic_read(&decoder->SurfacesFilled);
-#if 0
- // debug duplicate frames (done by VdpauAdvanceFrame)
- if (filled == 1) {
- decoder->FramesDuped++;
- Warning(_("video: display buffer empty, duping frame (%d/%d)\n"),
- decoder->FramesDuped, decoder->FrameCounter);
- if (!(decoder->FramesDisplayed % 300)) {
- VdpauPrintFrames(decoder);
- }
- }
-#endif
VdpauDisplayFrame();
@@ -4944,7 +5108,8 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
decoder->DropNextFrame = 1;
}
}
-
+#ifdef DEBUG
+ // debug audio/video sync
if (decoder->DupNextFrame || decoder->DropNextFrame
|| !(decoder->FramesDisplayed % (50 * 10))) {
static int64_t last_video_clock;
@@ -4957,6 +5122,7 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
last_video_clock = video_clock;
}
+#endif
}
///
@@ -4969,9 +5135,11 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
const AVCodecContext * video_ctx, const AVFrame * frame)
{
+#ifdef DEBUG
if (!atomic_read(&decoder->SurfacesFilled)) {
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
}
+#endif
if (decoder->DropNextFrame) { // drop frame requested
++decoder->FramesDropped;
@@ -5067,7 +5235,8 @@ static void VdpauDisplayHandlerThread(void)
clock_gettime(CLOCK_REALTIME, &nowtime);
// time for one frame over?
- if ((nowtime.tv_sec - decoder->FrameTime.tv_sec)
+ if ( //filled<VIDEO_SURFACES_MAX &&
+ (nowtime.tv_sec - decoder->FrameTime.tv_sec)
* 1000 * 1000 * 1000 + (nowtime.tv_nsec - decoder->FrameTime.tv_nsec) <
15 * 1000 * 1000) {
return;
@@ -5138,6 +5307,7 @@ static void VdpauOsdClear(void)
#endif
free(image);
+ VdpauShowOsd = 0;
}
///
@@ -5196,6 +5366,7 @@ static void VdpauUploadImage(int x, int y, int width, int height,
VdpauGetErrorString(status));
}
#endif
+ VdpauShowOsd = 1;
}
///
@@ -6192,6 +6363,30 @@ void VideoSetDeinterlace(int mode)
}
/**
+** Set skip chroma deinterlace on/off.
+*/
+void VideoSetSkipChromaDeinterlace(int onoff)
+{
+ VideoSkipChromaDeinterlace = onoff;
+}
+
+/**
+** Set denoise level (0 .. 1000).
+*/
+void VideoSetDenoise(int level)
+{
+ VideoDenoise = level;
+}
+
+/**
+** Set sharpness level (-1000 .. 1000).
+*/
+void VideoSetSharpen(int level)
+{
+ VideoSharpen = level;
+}
+
+/**
** Set scaling mode.
*/
void VideoSetScaling(int mode)
diff --git a/video.h b/video.h
index 5a03d4c..9962cf3 100644
--- a/video.h
+++ b/video.h
@@ -1,7 +1,7 @@
///
/// @file video.h @brief Video module header file
///
-/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved.
+/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -83,9 +83,18 @@ extern int VideoSetGeometry(const char *);
/// set deinterlace
extern void VideoSetDeinterlace(int);
+ /// set skip chroma deinterlace
+extern void VideoSetSkipChromaDeinterlace(int);
+
/// set scaling
extern void VideoSetScaling(int);
+ /// set denoise
+extern void VideoSetDenoise(int);
+
+ /// set sharpen
+extern void VideoSetSharpen(int);
+
/// set audio delay
extern void VideoSetAudioDelay(int);