Video improvements.

Fix generate of video output from StillPicture.
Add support for resolution dependend video parameterts (Deinterlace,
Scaling, Denoise, Sharpen, ...).
This commit is contained in:
Johns 2012-01-09 17:03:04 +01:00
parent 5e005eeff5
commit 96eefca699
7 changed files with 353 additions and 156 deletions

View File

@ -1,6 +1,10 @@
User johns User johns
Date: Date:
Add support of resolution dependend video parameters (deint, scale, ...).
Add support for recording play back.
Add workaround for alsa crash in snd_pcm_prepare.
Fix bug: audio crash on exit.
Fix build with vdr without yaepg support. Fix build with vdr without yaepg support.
Support yaepghd video picture output position change. Support yaepghd video picture output position change.

View File

@ -95,23 +95,27 @@ Setup: /etc/vdr/setup.conf
softhddevice.MakePrimary = 1 softhddevice.MakePrimary = 1
0 = no change, 1 make softhddevice primary at start 0 = no change, 1 make softhddevice primary at start
softhddevice.Deinterlace = 0 <res> of the next parameters is 567i, 720p, 1080i_fake or 1080i.
1080i_fake is 1280x1080 or 1440x1080
1080i is "real" 1920x1080
softhddevice.<res>.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
softhddevice.<res>.Deinterlace = 0
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software 0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
(only 0, 1 supported with vaapi) (only 0, 1 supported with vaapi)
softhddevice.SkipChromaDeinterlace = 0 softhddevice.<res>.SkipChromaDeinterlace = 0
0 = disabled, 1 = enabled (for slower cards, poor qualität) 0 = disabled, 1 = enabled (for slower cards, poor qualität)
softhddevice.Denoise = 0 softhddevice.<res>.Denoise = 0
0 .. 1000 noise reduction level (0 off, 1000 max) 0 .. 1000 noise reduction level (0 off, 1000 max)
softhddevice.Sharpness = 0 softhddevice.<res>.Sharpness = 0
-1000 .. 1000 noise reduction level (0 off, -1000 max blur, -1000 .. 1000 noise reduction level (0 off, -1000 max blur,
1000 max sharp) 1000 max sharp)
softhddevice.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
softhddevice.AudioDelay = 0 softhddevice.AudioDelay = 0
+n or -n ms +n or -n ms

1
Todo
View File

@ -93,3 +93,4 @@ setup:
Setup 4:3 zoom type Setup 4:3 zoom type
Setup parameters are not used until restart. Setup parameters are not used until restart.
Can a notice be added to the setup menu? Can a notice be added to the setup menu?
576i, 720p, fake 1080i, 1080i

View File

@ -818,14 +818,19 @@ void Freeze(void)
*/ */
void StillPicture(const uint8_t * data, int size) void StillPicture(const uint8_t * data, int size)
{ {
int i;
// must be a PES start code // must be a PES start code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) { if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
Error(_("[softhddev] invalid PES video packet\n")); Error(_("[softhddev] invalid PES video packet\n"));
return; return;
} }
PlayVideo(data, size); Clear(); // flush video buffers
PlayVideo(data, size); // +1 future for deinterlace
VideoNextPacket(VideoCodecID); // terminate work for (i = -1; i < (VideoCodecID == CODEC_ID_MPEG2VIDEO ? 3 : 17); ++i) {
PlayVideo(data, size); // reference frames
}
VideoNextPacket(VideoCodecID); // terminate last packet
} }
/** /**
@ -917,10 +922,10 @@ static char StartX11Server; ///< flag start the x11 server
*/ */
const char *CommandLineHelp(void) const char *CommandLineHelp(void)
{ {
return " -a device\talsa audio device (fe. hw:0,0)\n" return " -a device\taudio device (fe. alsa: hw:0,0 oss: /dev/dsp)\n"
" -d display\tdisplay of x11 server (f.e :0.0)\n" " -d display\tdisplay of x11 server (fe. :0.0)\n"
" -g geometry\tx11 window geometry wxh+x+y\n" " -g geometry\tx11 window geometry wxh+x+y\n"
" -x\tstart x11 server\n"; " -x\t\tstart x11 server\n";
} }
/** /**

View File

@ -51,14 +51,32 @@ static class cSoftHdDevice *MyDevice;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
#define RESOLUTIONS 4 ///< number of resolutions
static const char *const Resolution[RESOLUTIONS] = {
"576i", "720p", "1080i_fake", "1080i"
};
static char ConfigMakePrimary; ///< config primary wanted static char ConfigMakePrimary; ///< config primary wanted
static char ConfigVideoDeinterlace; ///< config deinterlace
static char ConfigVideoSkipChromaDeinterlace; ///< config skip chroma /// config deinterlace
static int ConfigVideoDenoise; ///< config denoise static int ConfigVideoDeinterlace[RESOLUTIONS];
static int ConfigVideoSharpen; ///< config sharpen
static char ConfigVideoScaling; ///< config scaling /// config skip chroma
static int ConfigVideoSkipChromaDeinterlace[RESOLUTIONS];
/// config denoise
static int ConfigVideoDenoise[RESOLUTIONS];
/// config sharpen
static int ConfigVideoSharpen[RESOLUTIONS];
/// config scaling
static int ConfigVideoScaling[RESOLUTIONS];
static int ConfigVideoAudioDelay; ///< config audio delay static int ConfigVideoAudioDelay; ///< config audio delay
static int ConfigAudioPassthrough; ///< config audio pass-through static int ConfigAudioPassthrough; ///< config audio pass-through
static volatile char DoMakePrimary; ///< flag switch primary static volatile char DoMakePrimary; ///< flag switch primary
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -153,12 +171,11 @@ void cSoftOsd::Flush(void)
if (!Active()) { if (!Active()) {
return; return;
} }
// support yaepghd, video window // support yaepghd, video window
#ifdef USE_YAEPG #ifdef USE_YAEPG
if (vidWin.bpp) { if (vidWin.bpp) {
dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, vidWin.Width(),
vidWin.Width(), vidWin.Height(), vidWin.x1, vidWin.y2 ); vidWin.Height(), vidWin.x1, vidWin.y2);
// FIXME: vidWin is OSD relative not video window. // FIXME: vidWin is OSD relative not video window.
VideoSetOutputPosition(Left() + vidWin.x1, Top() + vidWin.y1, VideoSetOutputPosition(Left() + vidWin.x1, Top() + vidWin.y1,
@ -289,11 +306,11 @@ class cMenuSetupSoft:public cMenuSetupPage
{ {
protected: protected:
int MakePrimary; int MakePrimary;
int Deinterlace; int Scaling[RESOLUTIONS];
int SkipChromaDeinterlace; int Deinterlace[RESOLUTIONS];
int Denoise; int SkipChromaDeinterlace[RESOLUTIONS];
int Sharpen; int Denoise[RESOLUTIONS];
int Scaling; int Sharpen[RESOLUTIONS];
int AudioDelay; int AudioDelay;
int AudioPassthrough; int AudioPassthrough;
protected: protected:
@ -302,6 +319,19 @@ class cMenuSetupSoft:public cMenuSetupPage
cMenuSetupSoft(void); cMenuSetupSoft(void);
}; };
/**
** Create a seperator item.
*/
static inline cOsdItem *SeparatorItem(const char *label)
{
cOsdItem *item;
item = new cOsdItem(cString::sprintf("* %s: ", label));
item->SetSelectable(false);
return item;
}
/** /**
** Constructor setup menu. ** Constructor setup menu.
*/ */
@ -316,26 +346,41 @@ cMenuSetupSoft::cMenuSetupSoft(void)
static const char *const passthrough[] = { static const char *const passthrough[] = {
"None", "AC-3" "None", "AC-3"
}; };
static const char *const resolution[RESOLUTIONS] = {
"576i", "720p", "fake 1080i", "1080i"
};
int i;
// cMenuEditBoolItem cMenuEditBitItem cMenuEditNumItem // cMenuEditBoolItem cMenuEditBitItem cMenuEditNumItem
// cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem // cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem
MakePrimary = ConfigMakePrimary; MakePrimary = ConfigMakePrimary;
Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary, Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary,
tr("no"), tr("yes"))); tr("no"), tr("yes")));
Deinterlace = ConfigVideoDeinterlace; //
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace, 5, // video
//
Add(SeparatorItem(tr("Video")));
for (i = 0; i < RESOLUTIONS; ++i) {
Add(SeparatorItem(resolution[i]));
Scaling[i] = ConfigVideoScaling[i];
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling[i], 4, scaling));
Deinterlace[i] = ConfigVideoDeinterlace[i];
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace[i], 5,
deinterlace)); deinterlace));
SkipChromaDeinterlace = ConfigVideoSkipChromaDeinterlace; SkipChromaDeinterlace[i] = ConfigVideoSkipChromaDeinterlace[i];
Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"), Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"),
&SkipChromaDeinterlace, tr("no"), tr("yes"))); &SkipChromaDeinterlace[i], tr("no"), tr("yes")));
Denoise = ConfigVideoDenoise; Denoise[i] = ConfigVideoDenoise[i];
Add(new cMenuEditIntItem(tr("Denoise (vdpau 0..1000)"), &Denoise, 0, Add(new cMenuEditIntItem(tr("Denoise (0..1000) (vdpau)"), &Denoise[i],
1000)); 0, 1000));
Sharpen = ConfigVideoSharpen; Sharpen[i] = ConfigVideoSharpen[i];
Add(new cMenuEditIntItem(tr("Sharpen (vdpau -1000..1000)"), &Sharpen, Add(new cMenuEditIntItem(tr("Sharpen (-1000..1000) (vdpau)"),
-1000, 1000)); &Sharpen[i], -1000, 1000));
Scaling = ConfigVideoScaling; }
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling, 4, scaling)); //
// audio
//
Add(SeparatorItem(tr("Audio")));
AudioDelay = ConfigVideoAudioDelay; AudioDelay = ConfigVideoAudioDelay;
Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000, Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000,
1000)); 1000));
@ -349,18 +394,32 @@ cMenuSetupSoft::cMenuSetupSoft(void)
*/ */
void cMenuSetupSoft::Store(void) void cMenuSetupSoft::Store(void)
{ {
int i;
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary); SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
SetupStore("Deinterlace", ConfigVideoDeinterlace = Deinterlace);
VideoSetDeinterlace(ConfigVideoDeinterlace); for (i = 0; i < RESOLUTIONS; ++i) {
SetupStore("SkipChromaDeinterlace", ConfigVideoSkipChromaDeinterlace = char buf[128];
SkipChromaDeinterlace);
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace); snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
SetupStore("Denoise", ConfigVideoDenoise = Denoise); SetupStore(buf, ConfigVideoScaling[i] = Scaling[i]);
VideoSetDenoise(ConfigVideoDenoise); snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
SetupStore("Sharpen", ConfigVideoSharpen = Sharpen); SetupStore(buf, ConfigVideoDeinterlace[i] = Deinterlace[i]);
VideoSetSharpen(ConfigVideoSharpen); snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
SetupStore("Scaling", ConfigVideoScaling = Scaling); "SkipChromaDeinterlace");
SetupStore(buf, ConfigVideoSkipChromaDeinterlace[i] =
SkipChromaDeinterlace[i]);
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
SetupStore(buf, ConfigVideoDenoise[i] = Denoise[i]);
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
SetupStore(buf, ConfigVideoSharpen[i] = Sharpen[i]);
}
VideoSetScaling(ConfigVideoScaling); VideoSetScaling(ConfigVideoScaling);
VideoSetDeinterlace(ConfigVideoDeinterlace);
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
VideoSetDenoise(ConfigVideoDenoise);
VideoSetSharpen(ConfigVideoSharpen);
SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay); SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
VideoSetAudioDelay(ConfigVideoAudioDelay); VideoSetAudioDelay(ConfigVideoAudioDelay);
SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough); SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough);
@ -553,7 +612,8 @@ void cSoftHdDevice::SetVolumeDevice(int volume)
*/ */
void cSoftHdDevice::StillPicture(const uchar * data, int length) void cSoftHdDevice::StillPicture(const uchar * data, int length)
{ {
dsyslog("[softhddev]%s:\n", __FUNCTION__); dsyslog("[softhddev]%s: %s\n", __FUNCTION__,
data[0] == 0x47 ? "ts" : "pes");
if (data[0] == 0x47) { // ts sync if (data[0] == 0x47) { // ts sync
cDevice::StillPicture(data, length); cDevice::StillPicture(data, length);
@ -860,34 +920,49 @@ cMenuSetupPage *cPluginSoftHdDevice::SetupMenu(void)
*/ */
bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value) bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
{ {
//dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value); int i;
char buf[128];
dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
// FIXME: handle the values // FIXME: handle the values
if (!strcmp(name, "MakePrimary")) { if (!strcmp(name, "MakePrimary")) {
ConfigMakePrimary = atoi(value); ConfigMakePrimary = atoi(value);
return true; return true;
} }
if (!strcmp(name, "Deinterlace")) { for (i = 0; i < RESOLUTIONS; ++i) {
VideoSetDeinterlace(ConfigVideoDeinterlace = atoi(value)); snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
if (!strcmp(name, buf)) {
ConfigVideoScaling[i] = atoi(value);
VideoSetScaling(ConfigVideoScaling);
return true; return true;
} }
if (!strcmp(name, "SkipChromaDeinterlace")) { snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace = if (!strcmp(name, buf)) {
atoi(value)); ConfigVideoDeinterlace[i] = atoi(value);
VideoSetDeinterlace(ConfigVideoDeinterlace);
return true; return true;
} }
if (!strcmp(name, "Denoise")) { snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
VideoSetDenoise(ConfigVideoDenoise = atoi(value)); "SkipChromaDeinterlace");
if (!strcmp(name, buf)) {
ConfigVideoSkipChromaDeinterlace[i] = atoi(value);
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
return true; return true;
} }
if (!strcmp(name, "Sharpen")) { snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
VideoSetSharpen(ConfigVideoSharpen = atoi(value)); if (!strcmp(name, buf)) {
ConfigVideoDenoise[i] = atoi(value);
VideoSetDenoise(ConfigVideoDenoise);
return true; return true;
} }
if (!strcmp(name, "Scaling")) { snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
VideoSetScaling(ConfigVideoScaling = atoi(value)); if (!strcmp(name, buf)) {
ConfigVideoSharpen[i] = atoi(value);
VideoSetSharpen(ConfigVideoSharpen);
return true; return true;
} }
}
if (!strcmp(name, "AudioDelay")) { if (!strcmp(name, "AudioDelay")) {
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value)); VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
return true; return true;

264
video.c
View File

@ -129,6 +129,18 @@
// Declarations // Declarations
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
///
/// Video resolutions selector.
///
typedef enum _video_resolutions_
{
VideoResolution567i, ///< ...x567 interlaced
VideoResolution720p, ///< ...x720 progressive
VideoResolutionFake1080i, ///< 1280x1080 1440x1080 interlaced
VideoResolution1080i, ///< 1920x1080 interlaced
VideoResolutionMax ///< number of resolution indexs
} VideoResolutions;
/// ///
/// Video deinterlace modes. /// Video deinterlace modes.
/// ///
@ -196,25 +208,25 @@ static int VideoWindowY; ///< video outout window y coordinate
static unsigned VideoWindowWidth; ///< video output window width static unsigned VideoWindowWidth; ///< video output window width
static unsigned VideoWindowHeight; ///< video output window height static unsigned VideoWindowHeight; ///< video output window height
/// Default deinterlace mode /// Default deinterlace mode.
static VideoDeinterlaceModes VideoDeinterlace; static VideoDeinterlaceModes VideoDeinterlace[VideoResolutionMax];
/// Default number of deinterlace surfaces /// Default number of deinterlace surfaces
static const int VideoDeinterlaceSurfaces = 4; static const int VideoDeinterlaceSurfaces = 4;
/// Default skip chroma deinterlace flag (VDPAU only) /// Default skip chroma deinterlace flag (VDPAU only)
static int VideoSkipChromaDeinterlace = 1; static int VideoSkipChromaDeinterlace[VideoResolutionMax];
/// Default amount of noise reduction algorithm to apply (0 .. 1000). /// Default amount of noise reduction algorithm to apply (0 .. 1000).
static int VideoDenoise; static int VideoDenoise[VideoResolutionMax];
/// Default amount of of sharpening, or blurring, to apply (-1000 .. 1000). /// Default amount of of sharpening, or blurring, to apply (-1000 .. 1000).
static int VideoSharpen; static int VideoSharpen[VideoResolutionMax];
// FIXME: color space // FIXME: color space / studio levels
/// Default scaling mode /// Default scaling mode
static VideoScalingModes VideoScaling; static VideoScalingModes VideoScaling[VideoResolutionMax];
/// Default audio/video delay /// Default audio/video delay
static int VideoAudioDelay; static int VideoAudioDelay;
@ -733,6 +745,38 @@ static void GlxExit(void)
#endif #endif
//----------------------------------------------------------------------------
// common functions
//----------------------------------------------------------------------------
///
/// Calculate resolution group.
///
/// @param width video picture raw width
/// @param height video picture raw height
/// @param interlace flag interlaced video picture
///
/// @note interlace isn't used yet and probably wrong set by caller.
///
static VideoResolutions VideoResolutionGroup(int width, int height,
__attribute__ ((unused))
int interlace)
{
if (height <= 567) {
return VideoResolution567i;
}
if (height <= 720) {
return VideoResolution720p;
}
if (height < 1080) {
return VideoResolutionFake1080i;
}
if (width < 1920) {
return VideoResolutionFake1080i;
}
return VideoResolution1080i;
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// auto-crop // auto-crop
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -862,7 +906,6 @@ typedef struct _vaapi_decoder_ VaapiDecoder;
struct _vaapi_decoder_ struct _vaapi_decoder_
{ {
VADisplay *VaDisplay; ///< VA-API display VADisplay *VaDisplay; ///< VA-API display
unsigned SurfaceFlags; ///< flags for put surface
xcb_window_t Window; ///< output window xcb_window_t Window; ///< output window
int OutputX; ///< output window x int OutputX; ///< output window x
@ -870,6 +913,10 @@ struct _vaapi_decoder_
int OutputWidth; ///< output window width int OutputWidth; ///< output window width
int OutputHeight; ///< output window height int OutputHeight; ///< output window height
/// flags for put surface for different resolutions groups
unsigned SurfaceFlagsTable[VideoResolutionMax];
unsigned SurfaceFlags; ///< current flags for put surface
enum PixelFormat PixFmt; ///< ffmpeg frame pixfmt enum PixelFormat PixFmt; ///< ffmpeg frame pixfmt
int WrongInterlacedWarned; ///< warning about interlace flag issued int WrongInterlacedWarned; ///< warning about interlace flag issued
int Interlaced; ///< ffmpeg interlaced flag int Interlaced; ///< ffmpeg interlaced flag
@ -892,6 +939,7 @@ struct _vaapi_decoder_
int InputWidth; ///< video input width int InputWidth; ///< video input width
int InputHeight; ///< video input height int InputHeight; ///< video input height
AVRational InputAspect; ///< video input aspect ratio AVRational InputAspect; ///< video input aspect ratio
VideoResolutions Resolution; ///< resolution group
int CropX; ///< video crop x int CropX; ///< video crop x
int CropY; ///< video crop y int CropY; ///< video crop y
@ -1127,6 +1175,63 @@ static void VaapiPrintFrames(const VaapiDecoder * decoder)
#endif #endif
} }
///
/// Initialize surface flags.
///
/// @param decoder video hardware decoder
///
static void VaapiInitSurfaceFlags(VaapiDecoder * decoder)
{
int i;
for (i = 0; i < VideoResolutionMax; ++i) {
decoder->SurfaceFlagsTable[i] = VA_CLEAR_DRAWABLE;
// FIXME: color space conversion none, ITU-R BT.601, ITU-R BT.709
decoder->SurfaceFlagsTable[i] |= VA_SRC_BT601;
// 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;
break;
case VideoScalingFast:
decoder->SurfaceFlagsTable[i] |= VA_FILTER_SCALING_FAST;
break;
case VideoScalingHQ:
// vdpau backend supports only VA_FILTER_SCALING_HQ
// vdpau backend with advanced deinterlacer and my GT-210
// is too slow
decoder->SurfaceFlagsTable[i] |= VA_FILTER_SCALING_HQ;
break;
case VideoScalingAnamorphic:
// intel backend supports only VA_FILTER_SCALING_NL_ANAMORPHIC;
// don't use it, its for 4:3 -> 16:9 scaling
decoder->SurfaceFlagsTable[i] |=
VA_FILTER_SCALING_NL_ANAMORPHIC;
break;
}
// deinterlace flags (not yet supported by libva)
switch (VideoDeinterlace[i]) {
case VideoDeinterlaceBob:
break;
case VideoDeinterlaceWeave:
break;
case VideoDeinterlaceTemporal:
//FIXME: private hack
//decoder->SurfaceFlagsTable[i] |= 0x00002000;
break;
case VideoDeinterlaceTemporalSpatial:
//FIXME: private hack
//decoder->SurfaceFlagsTable[i] |= 0x00006000;
break;
case VideoDeinterlaceSoftware:
break;
}
}
}
/// ///
/// Allocate new VA-API decoder. /// Allocate new VA-API decoder.
/// ///
@ -1147,49 +1252,8 @@ static VaapiDecoder *VaapiNewDecoder(void)
decoder->VaDisplay = VaDisplay; decoder->VaDisplay = VaDisplay;
decoder->Window = VideoWindow; decoder->Window = VideoWindow;
decoder->SurfaceFlags = VA_CLEAR_DRAWABLE; VaapiInitSurfaceFlags(decoder);
// color space conversion none, ITU-R BT.601, ITU-R BT.709 decoder->SurfaceFlags = decoder->SurfaceFlagsTable[0];
decoder->SurfaceFlags |= VA_SRC_BT601;
// scaling flags FAST, HQ, NL_ANAMORPHIC
// FIXME: need to detect the backend to choose the parameter
switch (VideoScaling) {
case VideoScalingNormal:
decoder->SurfaceFlags |= VA_FILTER_SCALING_DEFAULT;
break;
case VideoScalingFast:
decoder->SurfaceFlags |= VA_FILTER_SCALING_FAST;
break;
case VideoScalingHQ:
// vdpau backend supports only VA_FILTER_SCALING_HQ
// vdpau backend with advanced deinterlacer and my GT-210
// is too slow
decoder->SurfaceFlags |= VA_FILTER_SCALING_HQ;
break;
case VideoScalingAnamorphic:
// intel backend supports only VA_FILTER_SCALING_NL_ANAMORPHIC;
// don't use it, its for 4:3 -> 16:9 scaling
decoder->SurfaceFlags |= VA_FILTER_SCALING_NL_ANAMORPHIC;
break;
}
// deinterlace flags (not yet supported by libva)
switch (VideoDeinterlace) {
case VideoDeinterlaceBob:
break;
case VideoDeinterlaceWeave:
break;
case VideoDeinterlaceTemporal:
//FIXME: private hack
//decoder->SurfaceFlags |= 0x00002000;
break;
case VideoDeinterlaceTemporalSpatial:
//FIXME: private hack
//decoder->SurfaceFlags |= 0x00006000;
break;
case VideoDeinterlaceSoftware:
break;
}
decoder->DeintImages[0].image_id = VA_INVALID_ID; decoder->DeintImages[0].image_id = VA_INVALID_ID;
decoder->DeintImages[1].image_id = VA_INVALID_ID; decoder->DeintImages[1].image_id = VA_INVALID_ID;
@ -1719,7 +1783,13 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
Error(_("codec: can't create config")); Error(_("codec: can't create config"));
goto slow_path; goto slow_path;
} }
// FIXME: need only to create and destroy surfaces for size changes! // FIXME: interlaced not valid here?
decoder->Resolution =
VideoResolutionGroup(video_ctx->width, video_ctx->height,
decoder->Interlaced);
decoder->SurfaceFlags = decoder->SurfaceFlagsTable[decoder->Resolution];
// FIXME: need only to create and destroy surfaces for size changes
// or when number of needed surfaces changed!
VaapiCreateSurfaces(decoder, video_ctx->width, video_ctx->height); VaapiCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
// bind surfaces to context // bind surfaces to context
@ -1789,7 +1859,8 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface,
VAStatus status; VAStatus status;
// deinterlace // deinterlace
if (interlaced && VideoDeinterlace != VideoDeinterlaceWeave) { if (interlaced
&& VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
if (top_field_first) { if (top_field_first) {
if (field) { if (field) {
type = VA_BOTTOM_FIELD; type = VA_BOTTOM_FIELD;
@ -1914,7 +1985,8 @@ static void VaapiPutSurfaceGLX(VaapiDecoder * decoder, VASurfaceID surface,
uint32_t end; uint32_t end;
// deinterlace // deinterlace
if (interlaced && VideoDeinterlace != VideoDeinterlaceWeave) { if (interlaced
&& VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
if (top_field_first) { if (top_field_first) {
if (field) { if (field) {
type = VA_BOTTOM_FIELD; type = VA_BOTTOM_FIELD;
@ -2052,6 +2124,10 @@ static void VaapiSetup(VaapiDecoder * decoder,
"video/vaapi: created image %dx%d with id 0x%08x and buffer id 0x%08x\n", "video/vaapi: created image %dx%d with id 0x%08x and buffer id 0x%08x\n",
width, height, decoder->Image->image_id, decoder->Image->buf); width, height, decoder->Image->image_id, decoder->Image->buf);
// FIXME: interlaced not valid here?
decoder->Resolution =
VideoResolutionGroup(width, height, decoder->Interlaced);
decoder->SurfaceFlags = decoder->SurfaceFlagsTable[decoder->Resolution];
VaapiCreateSurfaces(decoder, width, height); VaapiCreateSurfaces(decoder, width, height);
#ifdef USE_GLX #ifdef USE_GLX
@ -2529,7 +2605,8 @@ static void VaapiRenderFrame(VaapiDecoder * decoder,
} }
#endif #endif
if (VideoDeinterlace == VideoDeinterlaceSoftware && interlaced) { if (VideoDeinterlace[decoder->Resolution] == VideoDeinterlaceSoftware
&& interlaced) {
// FIXME: software deinterlace avpicture_deinterlace // FIXME: software deinterlace avpicture_deinterlace
VaapiCpuDeinterlace(decoder, surface); VaapiCpuDeinterlace(decoder, surface);
} else { } else {
@ -2729,7 +2806,7 @@ static void VaapiDisplayFrame(void)
// FIXME: buggy libva-driver-vdpau, buggy libva-driver-intel // FIXME: buggy libva-driver-vdpau, buggy libva-driver-intel
&& (VaapiBuggyVdpau || (0 && VaapiBuggyIntel && (VaapiBuggyVdpau || (0 && VaapiBuggyIntel
&& decoder->InputHeight == 1080)) && decoder->InputHeight == 1080))
&& VideoDeinterlace != VideoDeinterlaceWeave) { && VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced, VaapiPutSurfaceX11(decoder, surface, decoder->Interlaced,
decoder->TopFieldFirst, 0); decoder->TopFieldFirst, 0);
put1 = GetMsTicks(); put1 = GetMsTicks();
@ -3206,6 +3283,7 @@ typedef struct _vdpau_decoder_
int InputWidth; ///< video input width int InputWidth; ///< video input width
int InputHeight; ///< video input height int InputHeight; ///< video input height
AVRational InputAspect; ///< video input aspect ratio AVRational InputAspect; ///< video input aspect ratio
VideoResolutions Resolution; ///< resolution group
int CropX; ///< video crop x int CropX; ///< video crop x
int CropY; ///< video crop y int CropY; ///< video crop y
@ -3588,8 +3666,10 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
// //
feature_n = 0; feature_n = 0;
if (VdpauTemporal) { if (VdpauTemporal) {
enables[feature_n] = (VideoDeinterlace == VideoDeinterlaceTemporal enables[feature_n] =
|| (VideoDeinterlace == VideoDeinterlaceTemporalSpatial (VideoDeinterlace[decoder->Resolution] == VideoDeinterlaceTemporal
|| (VideoDeinterlace[decoder->Resolution] ==
VideoDeinterlaceTemporalSpatial
&& !VdpauTemporalSpatial)) ? VDP_TRUE : VDP_FALSE; && !VdpauTemporalSpatial)) ? VDP_TRUE : VDP_FALSE;
features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL; features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL;
Debug(3, "video/vdpau: temporal deinterlace %s\n", Debug(3, "video/vdpau: temporal deinterlace %s\n",
@ -3597,7 +3677,7 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
} }
if (VdpauTemporalSpatial) { if (VdpauTemporalSpatial) {
enables[feature_n] = enables[feature_n] =
VideoDeinterlace == VideoDeinterlace[decoder->Resolution] ==
VideoDeinterlaceTemporalSpatial ? VDP_TRUE : VDP_FALSE; VideoDeinterlaceTemporalSpatial ? VDP_TRUE : VDP_FALSE;
features[feature_n++] = features[feature_n++] =
VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL; VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL_SPATIAL;
@ -3611,13 +3691,15 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
enables[feature_n - 1] ? "enabled" : "disabled"); enables[feature_n - 1] ? "enabled" : "disabled");
} }
if (VdpauNoiseReduction) { if (VdpauNoiseReduction) {
enables[feature_n] = VideoDenoise ? VDP_TRUE : VDP_FALSE; enables[feature_n] =
VideoDenoise[decoder->Resolution] ? VDP_TRUE : VDP_FALSE;
features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION; features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION;
Debug(3, "video/vdpau: noise reduction %s\n", Debug(3, "video/vdpau: noise reduction %s\n",
enables[feature_n - 1] ? "enabled" : "disabled"); enables[feature_n - 1] ? "enabled" : "disabled");
} }
if (VdpauSharpness) { if (VdpauSharpness) {
enables[feature_n] = VideoSharpen ? VDP_TRUE : VDP_FALSE; enables[feature_n] =
VideoSharpen[decoder->Resolution] ? VDP_TRUE : VDP_FALSE;
features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS; features[feature_n++] = VDP_VIDEO_MIXER_FEATURE_SHARPNESS;
Debug(3, "video/vdpau: sharpness %s\n", Debug(3, "video/vdpau: sharpness %s\n",
enables[feature_n - 1] ? "enabled" : "disabled"); enables[feature_n - 1] ? "enabled" : "disabled");
@ -3625,7 +3707,8 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
for (i = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1; for (i = VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1;
i <= VdpauHqScalingMax; ++i) { i <= VdpauHqScalingMax; ++i) {
enables[feature_n] = enables[feature_n] =
VideoScaling == VideoScalingHQ ? VDP_TRUE : VDP_FALSE; VideoScaling[decoder->Resolution] ==
VideoScalingHQ ? VDP_TRUE : VDP_FALSE;
features[feature_n++] = i; features[feature_n++] = i;
Debug(3, "video/vdpau: high quality scaling %d %s\n", Debug(3, "video/vdpau: high quality scaling %d %s\n",
1 + i - VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1, 1 + i - VDP_VIDEO_MIXER_FEATURE_HIGH_QUALITY_SCALING_L1,
@ -3646,7 +3729,7 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
*/ */
attribute_n = 0; attribute_n = 0;
if (VdpauSkipChroma) { if (VdpauSkipChroma) {
skip_chroma_value = VideoSkipChromaDeinterlace; skip_chroma_value = VideoSkipChromaDeinterlace[decoder->Resolution];
attributes[attribute_n] attributes[attribute_n]
= VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE; = VDP_VIDEO_MIXER_ATTRIBUTE_SKIP_CHROMA_DEINTERLACE;
attribute_value_ptrs[attribute_n++] = &skip_chroma_value; attribute_value_ptrs[attribute_n++] = &skip_chroma_value;
@ -3654,7 +3737,7 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
skip_chroma_value ? "enabled" : "disabled"); skip_chroma_value ? "enabled" : "disabled");
} }
if (VdpauNoiseReduction) { if (VdpauNoiseReduction) {
noise_reduction_level = VideoDenoise / 1000.0; noise_reduction_level = VideoDenoise[decoder->Resolution] / 1000.0;
attributes[attribute_n] attributes[attribute_n]
= VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL; = VDP_VIDEO_MIXER_ATTRIBUTE_NOISE_REDUCTION_LEVEL;
attribute_value_ptrs[attribute_n++] = &noise_reduction_level; attribute_value_ptrs[attribute_n++] = &noise_reduction_level;
@ -3662,7 +3745,7 @@ static void VdpauMixerSetup(VdpauDecoder * decoder)
noise_reduction_level); noise_reduction_level);
} }
if (VdpauSharpness) { if (VdpauSharpness) {
sharpness_level = VideoSharpen / 1000.0; sharpness_level = VideoSharpen[decoder->Resolution] / 1000.0;
attributes[attribute_n] attributes[attribute_n]
= VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL; = VDP_VIDEO_MIXER_ATTRIBUTE_SHARPNESS_LEVEL;
attribute_value_ptrs[attribute_n++] = &sharpness_level; attribute_value_ptrs[attribute_n++] = &sharpness_level;
@ -4488,6 +4571,7 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
abort(); abort();
goto slow_path; goto slow_path;
} }
// FIXME: Combine this with VdpauSetup
decoder->CropX = 0; decoder->CropX = 0;
decoder->CropY = 0; decoder->CropY = 0;
@ -4501,7 +4585,11 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
VdpauMixerSetup(decoder); VdpauMixerSetup(decoder);
// FIXME: need only to create and destroy surfaces for size changes! // FIXME: need only to create and destroy surfaces for size changes
// or when number of needed surfaces changed!
decoder->Resolution =
VideoResolutionGroup(video_ctx->width, video_ctx->height,
decoder->Interlaced);
VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height); VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
Debug(3, "\t%#010x %s\n", fmt_idx[0], av_get_pix_fmt_name(fmt_idx[0])); Debug(3, "\t%#010x %s\n", fmt_idx[0], av_get_pix_fmt_name(fmt_idx[0]));
@ -4532,6 +4620,9 @@ static void VdpauSetup(VdpauDecoder * decoder,
VdpauCleanup(decoder); VdpauCleanup(decoder);
VdpauMixerSetup(decoder); VdpauMixerSetup(decoder);
decoder->Resolution =
VideoResolutionGroup(video_ctx->width, video_ctx->height,
decoder->Interlaced);
VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height); VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
// get real surface size // get real surface size
@ -4742,7 +4833,8 @@ static void VdpauRenderFrame(VdpauDecoder * decoder,
} }
#endif #endif
if (VideoDeinterlace == VideoDeinterlaceSoftware && interlaced) { if (VideoDeinterlace[decoder->Resolution] == VideoDeinterlaceSoftware
&& interlaced) {
// FIXME: software deinterlace avpicture_deinterlace // FIXME: software deinterlace avpicture_deinterlace
// FIXME: VdpauCpuDeinterlace(decoder, surface); // FIXME: VdpauCpuDeinterlace(decoder, surface);
} else { } else {
@ -4940,7 +5032,8 @@ static void VdpauMixVideo(VdpauDecoder * decoder)
VdpauGrabSurface(decoder); VdpauGrabSurface(decoder);
#endif #endif
if (decoder->Interlaced && VideoDeinterlace != VideoDeinterlaceWeave) { if (decoder->Interlaced
&& VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
// //
// Build deinterlace structures // Build deinterlace structures
// //
@ -6576,41 +6669,56 @@ void VideoSetOutputPosition(int x, int y, int width, int height)
/// ///
/// Set deinterlace mode. /// Set deinterlace mode.
/// ///
void VideoSetDeinterlace(int mode) void VideoSetDeinterlace(int mode[VideoResolutionMax])
{ {
VideoDeinterlace = mode; VideoDeinterlace[0] = mode[0];
VideoDeinterlace[1] = mode[1];
VideoDeinterlace[2] = mode[2];
VideoDeinterlace[3] = mode[3];
} }
/// ///
/// Set skip chroma deinterlace on/off. /// Set skip chroma deinterlace on/off.
/// ///
void VideoSetSkipChromaDeinterlace(int onoff) void VideoSetSkipChromaDeinterlace(int onoff[VideoResolutionMax])
{ {
VideoSkipChromaDeinterlace = onoff; VideoSkipChromaDeinterlace[0] = onoff[0];
VideoSkipChromaDeinterlace[1] = onoff[1];
VideoSkipChromaDeinterlace[2] = onoff[2];
VideoSkipChromaDeinterlace[3] = onoff[3];
} }
/// ///
/// Set denoise level (0 .. 1000). /// Set denoise level (0 .. 1000).
/// ///
void VideoSetDenoise(int level) void VideoSetDenoise(int level[VideoResolutionMax])
{ {
VideoDenoise = level; VideoDenoise[0] = level[0];
VideoSharpen[1] = level[1];
VideoSharpen[2] = level[2];
VideoSharpen[3] = level[3];
} }
/// ///
/// Set sharpness level (-1000 .. 1000). /// Set sharpness level (-1000 .. 1000).
/// ///
void VideoSetSharpen(int level) void VideoSetSharpen(int level[VideoResolutionMax])
{ {
VideoSharpen = level; VideoSharpen[0] = level[0];
VideoSharpen[1] = level[1];
VideoSharpen[2] = level[2];
VideoSharpen[3] = level[3];
} }
/// ///
/// Set scaling mode. /// Set scaling mode.
/// ///
void VideoSetScaling(int mode) void VideoSetScaling(int mode[VideoResolutionMax])
{ {
VideoScaling = mode; VideoScaling[0] = mode[0];
VideoScaling[1] = mode[1];
VideoScaling[2] = mode[2];
VideoScaling[3] = mode[3];
} }
/// ///

10
video.h
View File

@ -77,19 +77,19 @@ extern int VideoSetGeometry(const char *);
extern void VideoSetOutputPosition(int, int, int, int); extern void VideoSetOutputPosition(int, int, int, int);
/// Set deinterlace. /// Set deinterlace.
extern void VideoSetDeinterlace(int); extern void VideoSetDeinterlace(int[]);
/// Set skip chroma deinterlace. /// Set skip chroma deinterlace.
extern void VideoSetSkipChromaDeinterlace(int); extern void VideoSetSkipChromaDeinterlace(int[]);
/// Set scaling. /// Set scaling.
extern void VideoSetScaling(int); extern void VideoSetScaling(int[]);
/// Set denoise. /// Set denoise.
extern void VideoSetDenoise(int); extern void VideoSetDenoise(int[]);
/// Set sharpen. /// Set sharpen.
extern void VideoSetSharpen(int); extern void VideoSetSharpen(int[]);
/// Set audio delay. /// Set audio delay.
extern void VideoSetAudioDelay(int); extern void VideoSetAudioDelay(int);