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.
This commit is contained in:
Johns 2012-01-05 17:20:44 +01:00
parent aba14813c0
commit 0776bc5ee4
6 changed files with 385 additions and 117 deletions

View File

@ -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.

View File

@ -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

8
Todo
View File

@ -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.

View File

@ -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;

385
video.c
View File

@ -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
@ -4337,6 +4412,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.
///
@ -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;
// 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];
}
} 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];
}
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];
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;
}
///
@ -6191,6 +6362,30 @@ void VideoSetDeinterlace(int mode)
VideoDeinterlace = 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.
*/

11
video.h
View File

@ -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);