VDPAU: Add auto-crop support.

This commit is contained in:
Johns 2012-01-20 15:33:37 +01:00
parent eb024558de
commit 0422b6aa5a
7 changed files with 318 additions and 26 deletions

View File

@ -1,7 +1,8 @@
User johns User johns
Date: Date:
Release Version 0.3.6 Release Version 0.4.0
VDPAU: Add auto-crop support.
VDPAU: Changed OSD alpha calculation. VDPAU: Changed OSD alpha calculation.
Fix bug: Used VideoSharpen for denoise settings. Fix bug: Used VideoSharpen for denoise settings.
Instant update deinterlace/... configuration changes. Instant update deinterlace/... configuration changes.

View File

@ -24,17 +24,20 @@ A software and GPU emulated HD output device plugin for VDR.
o Video CPU/VA-API o Video CPU/VA-API
o Video VDPAU/VDPAU o Video VDPAU/VDPAU
o Video CPU/VDPAU o Video CPU/VDPAU
o Audio FFMpeg/Alsa/Analog
o Audio FFMpeg/Alsa/Digital
o Audio FFMpeg/OSS/Analog
o HDMI/SPDIF Passthrough
o VA-API bob software deinterlace
o Auto-crop
o planned: Video VA-API/Opengl o planned: Video VA-API/Opengl
o planned: Video VDPAU/Opengl o planned: Video VDPAU/Opengl
o planned: Video CPU/Xv o planned: Video CPU/Xv
o planned: Video CPU/Opengl o planned: Video CPU/Opengl
o planned: Software Deinterlacer o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
o planned: Video XvBA/XvBA o planned: Video XvBA/XvBA
o Audio FFMpeg/Alsa/Analog o planned: atmo light support
o Audio FFMpeg/Alsa/Digital
o Audio FFMpeg/OSS/Analog
o Alsa HDMI/SPDIF Passthrough
o planned: OSS HDMI/SPDIF Passthrough
To compile you must have the 'requires' installed. To compile you must have the 'requires' installed.
@ -125,6 +128,14 @@ Setup: /etc/vdr/setup.conf
softhddevice.AudioPassthrough = 0 softhddevice.AudioPassthrough = 0
0 = none, 1 = AC-3 0 = none, 1 = AC-3
softhddevice.AutoCrop.Interval = 0
0 disables auto-crop
n each 'n' frames auto-crop is checked.
softhddevice.AutoCrop.Delay = 0
if auto-crop is over after 'n' intervals the same, the cropping is
used.
Setup: /etc/vdr/remote.conf Setup: /etc/vdr/remote.conf
------ ------

2
Todo
View File

@ -21,7 +21,6 @@ $Id: $
missing: missing:
software deinterlace (yadif, ...) software deinterlace (yadif, ...)
software decoder with software deinterlace software decoder with software deinterlace
auto crop
zoom/fit-zoom 4:3 (SetVideoDisplayFormat, SetVideoFormat?) zoom/fit-zoom 4:3 (SetVideoDisplayFormat, SetVideoFormat?)
ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)? ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)?
suspend output / energie saver: stop audio, stop video, configurable suspend output / energie saver: stop audio, stop video, configurable
@ -41,6 +40,7 @@ libva:
hard channel switch hard channel switch
yaepghd (VaapiSetOutputPosition) support yaepghd (VaapiSetOutputPosition) support
can associate ony displayed part of osd can associate ony displayed part of osd
auto crop for va-api
libva-intel-driver: libva-intel-driver:
intel still has hangups most with 1080i intel still has hangups most with 1080i

View File

@ -2125,7 +2125,7 @@ void AudioExit(void)
#ifdef USE_AUDIO_THREAD #ifdef USE_AUDIO_THREAD
AudioExitThread(); AudioExitThread();
#endif #endif
if ( UsedAudioModule ) { if (UsedAudioModule) {
UsedAudioModule->Exit(); UsedAudioModule->Exit();
} }
#ifdef USE_AUDIORING #ifdef USE_AUDIORING

View File

@ -42,7 +42,7 @@ extern "C"
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
static const char *const VERSION = "0.3.5"; static const char *const VERSION = "0.4.0";
static const char *const DESCRIPTION = static const char *const DESCRIPTION =
trNOOP("A software and GPU emulated HD device"); trNOOP("A software and GPU emulated HD device");
@ -79,6 +79,9 @@ 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 int ConfigAutoCropInterval; ///< auto crop detection interval
static int ConfigAutoCropDelay; ///< auto crop detection delay
static volatile char DoMakePrimary; ///< flag switch primary static volatile char DoMakePrimary; ///< flag switch primary
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -362,6 +365,8 @@ class cMenuSetupSoft:public cMenuSetupPage
int Sharpen[RESOLUTIONS]; int Sharpen[RESOLUTIONS];
int AudioDelay; int AudioDelay;
int AudioPassthrough; int AudioPassthrough;
int AutoCropInterval;
int AutoCropDelay;
protected: protected:
virtual void Store(void); virtual void Store(void);
public: public:
@ -370,6 +375,8 @@ class cMenuSetupSoft:public cMenuSetupPage
/** /**
** Create a seperator item. ** Create a seperator item.
**
** @param label text inside separator
*/ */
static inline cOsdItem *SeparatorItem(const char *label) static inline cOsdItem *SeparatorItem(const char *label)
{ {
@ -439,6 +446,16 @@ cMenuSetupSoft::cMenuSetupSoft(void)
AudioPassthrough = ConfigAudioPassthrough; AudioPassthrough = ConfigAudioPassthrough;
Add(new cMenuEditStraItem(tr("Audio pass-through"), &AudioPassthrough, 2, Add(new cMenuEditStraItem(tr("Audio pass-through"), &AudioPassthrough, 2,
passthrough)); passthrough));
//
// auto-crop
//
Add(SeparatorItem(tr("Auto-crop")));
AutoCropInterval = ConfigAutoCropInterval;
Add(new cMenuEditIntItem(tr("autocrop interval (frames)"),
&AutoCropInterval, 0, 200));
AutoCropDelay = ConfigAutoCropDelay;
Add(new cMenuEditIntItem(tr("autocrop delay (n * interval)"),
&AutoCropDelay, 0, 200));
} }
/** /**
@ -478,6 +495,11 @@ void cMenuSetupSoft::Store(void)
VideoSetAudioDelay(ConfigVideoAudioDelay); VideoSetAudioDelay(ConfigVideoAudioDelay);
SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough); SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough);
CodecSetAudioPassthrough(ConfigAudioPassthrough); CodecSetAudioPassthrough(ConfigAudioPassthrough);
SetupStore("AutoCrop.Interval", ConfigAutoCropInterval = AutoCropInterval);
SetupStore("AutoCrop.Delay", ConfigAutoCropDelay = AutoCropDelay);
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@ -1001,11 +1023,15 @@ cMenuSetupPage *cPluginSoftHdDevice::SetupMenu(void)
/** /**
** Parse setup parameters ** Parse setup parameters
**
** @param name paramter name (case sensetive)
** @param value value as string
**
** @returns true if the parameter is supported.
*/ */
bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value) bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
{ {
int i; int i;
char buf[128];
//dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value); //dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
@ -1018,6 +1044,8 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true; return true;
} }
for (i = 0; i < RESOLUTIONS; ++i) { for (i = 0; i < RESOLUTIONS; ++i) {
char buf[128];
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling"); snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
if (!strcmp(name, buf)) { if (!strcmp(name, buf)) {
ConfigVideoScaling[i] = atoi(value); ConfigVideoScaling[i] = atoi(value);
@ -1050,6 +1078,7 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true; return true;
} }
} }
if (!strcmp(name, "AudioDelay")) { if (!strcmp(name, "AudioDelay")) {
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value)); VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
return true; return true;
@ -1059,6 +1088,17 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true; return true;
} }
if (!strcmp(name, "AutoCrop.Interval")) {
VideoSetAutoCrop(ConfigAutoCropInterval =
atoi(value), ConfigAutoCropDelay);
return true;
}
if (!strcmp(name, "AutoCrop.Delay")) {
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay =
atoi(value));
return true;
}
return false; return false;
} }

267
video.c
View File

@ -37,6 +37,7 @@
/// ///
#define USE_XLIB_XCB ///< use xlib/xcb backend #define USE_XLIB_XCB ///< use xlib/xcb backend
#define USE_AUTOCROP ///< compile autocrop support
#define noUSE_GRAB ///< experimental grab code #define noUSE_GRAB ///< experimental grab code
#define noUSE_GLX ///< outdated GLX code #define noUSE_GLX ///< outdated GLX code
#define noUSE_DOUBLEBUFFER ///< use GLX double buffers #define noUSE_DOUBLEBUFFER ///< use GLX double buffers
@ -820,20 +821,31 @@ static VideoResolutions VideoResolutionGroup(int width, int height,
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/// ///
/// avfilter_vf_cropdetect /// Autocrop context structure and typedef.
/// ///
typedef struct _video_auto_crop_ctx_ typedef struct _auto_crop_ctx_
{ {
int x1; ///< detected left border int X1; ///< detected left border
int x2; ///< detected right border int X2; ///< detected right border
int y1; ///< detected top border int Y1; ///< detected top border
int y2; ///< detected bottom border int Y2; ///< detected bottom border
} VideoAutoCropCtx;
int Count; ///< counter to delay switch
int State; ///< autocrop state (0, 14, 16)
} AutoCropCtx;
#ifdef USE_AUTOCROP
#define YBLACK 0x20 ///< below is black #define YBLACK 0x20 ///< below is black
#define UVBLACK 0x80 ///< around is black #define UVBLACK 0x80 ///< around is black
#define M64 UINT64_C(0x0101010101010101) ///< 64bit multiplicator #define M64 UINT64_C(0x0101010101010101) ///< 64bit multiplicator
/// percent of width to ignore logos
static const int AutoCropLogoIgnore = 24;
static int AutoCropInterval; ///< check interval
static int AutoCropDelay; ///< switch delay
/// ///
/// Detect black line Y. /// Detect black line Y.
/// ///
@ -872,8 +884,19 @@ static int AutoCropIsBlackLineY(const uint8_t * data, int length, int stride)
/// ///
/// Auto detect black borders and crop them. /// Auto detect black borders and crop them.
/// ///
static void AutoCropDetect(int width, int height, void *data[3], /// @param autocrop autocrop variables
uint32_t pitches[3]) /// @param width frame width in pixel
/// @param height frame height in pixel
/// @param data frame planes data (Y, U, V)
/// @param pitches frame planes pitches (Y, U, V)
///
/// @note FIXME: can reduce the checked range, left, right crop isn't
/// used yet.
///
/// @note FIXME: only Y is checked, for black.
///
static void AutoCropDetect(AutoCropCtx * autocrop, int width, int height,
void *data[3], uint32_t pitches[3])
{ {
const void *data_y; const void *data_y;
unsigned length_y; unsigned length_y;
@ -886,15 +909,15 @@ static void AutoCropDetect(int width, int height, void *data[3],
int logo_skip; int logo_skip;
// //
// ignore top+bottom 4 lines and left+right 8 pixels // ignore top+bottom 6 lines and left+right 8 pixels
// //
#define SKIP_X 8 #define SKIP_X 8
#define SKIP_Y 4 #define SKIP_Y 6
x1 = width - 1; x1 = width - 1;
x2 = 0; x2 = 0;
y1 = height - 1; y1 = height - 1;
y2 = 0; y2 = 0;
logo_skip = SKIP_X; logo_skip = SKIP_X + (((width * AutoCropLogoIgnore) / 100 + 8) / 8) * 8;
data_y = data[0]; data_y = data[0];
length_y = pitches[0]; length_y = pitches[0];
@ -957,12 +980,21 @@ static void AutoCropDetect(int width, int height, void *data[3],
Debug(3, "video/autocrop: top=%d bottom=%d left=%d right=%d\n", y1, y2, Debug(3, "video/autocrop: top=%d bottom=%d left=%d right=%d\n", y1, y2,
x1, x2); x1, x2);
} }
autocrop->X1 = x1;
autocrop->X2 = x2;
autocrop->Y1 = y1;
autocrop->Y2 = y2;
} }
#endif
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// software - deinterlace // software - deinterlace
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// FIXME: move general software deinterlace functions to here.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// VA-API // VA-API
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1703,6 +1735,9 @@ static void VaapiUpdateOutput(VaapiDecoder * decoder)
} }
Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth, Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth,
decoder->OutputHeight, decoder->OutputX, decoder->OutputY); decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
//decoder->AutoCrop->State = 0;
//decoder->AutoCrop->Count = 0;
} }
/// ///
@ -3698,6 +3733,8 @@ typedef struct _vdpau_decoder_
int CropWidth; ///< video crop width int CropWidth; ///< video crop width
int CropHeight; ///< video crop height int CropHeight; ///< video crop height
AutoCropCtx AutoCrop[1]; ///< autocrop variables
#ifdef noyetUSE_GLX #ifdef noyetUSE_GLX
GLuint GlTexture[2]; ///< gl texture for VDPAU GLuint GlTexture[2]; ///< gl texture for VDPAU
void *GlxSurface[2]; ///< VDPAU/GLX surface void *GlxSurface[2]; ///< VDPAU/GLX surface
@ -4906,6 +4943,7 @@ static void VdpauUpdateOutput(VdpauDecoder * decoder)
case VideoStretch: case VideoStretch:
case VideoZoom: case VideoZoom:
case VideoAnamorphic: case VideoAnamorphic:
// AutoCrop
break; break;
} }
} }
@ -4925,6 +4963,9 @@ static void VdpauUpdateOutput(VdpauDecoder * decoder)
} }
Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth, Debug(3, "video: aspect output %dx%d+%d+%d\n", decoder->OutputWidth,
decoder->OutputHeight, decoder->OutputX, decoder->OutputY); decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
decoder->AutoCrop->State = 0;
decoder->AutoCrop->Count = 0;
} }
/// ///
@ -5162,6 +5203,8 @@ static void VdpauSetup(VdpauDecoder * decoder,
// //
} }
#ifdef USE_GRAB
/// ///
/// Grab video surface. /// Grab video surface.
/// ///
@ -5213,6 +5256,9 @@ static void VdpauGrabSurface(VdpauDecoder * decoder)
data[2] = base + width * height + width * height / 4; data[2] = base + width * height + width * height / 4;
format = VDP_YCBCR_FORMAT_YV12; format = VDP_YCBCR_FORMAT_YV12;
break; break;
default:
Error(_("video/vdpau: unsupported chroma type %d\n"), chroma_type);
return;
} }
status = VdpauVideoSurfaceGetBitsYCbCr(surface, format, data, pitches); status = VdpauVideoSurfaceGetBitsYCbCr(surface, format, data, pitches);
if (status != VDP_STATUS_OK) { if (status != VDP_STATUS_OK) {
@ -5221,11 +5267,165 @@ static void VdpauGrabSurface(VdpauDecoder * decoder)
return; return;
} }
AutoCropDetect(width, height, data, pitches);
free(base); free(base);
} }
#endif
#ifdef USE_AUTOCROP
///
/// VDPAU Auto crop support.
///
/// @param decoder VDPAU hw decoder
///
static void VdpauAutoCrop(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];
int crop14;
int crop16;
int next_state;
VdpYCbCrFormat format;
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;
default:
Error(_("video/vdpau: unsupported chroma type %d\n"), chroma_type);
return;
}
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;
}
AutoCropDetect(decoder->AutoCrop, width, height, data, pitches);
free(base);
// ignore black frames
if (decoder->AutoCrop->Y1 >= decoder->AutoCrop->Y2) {
return;
}
crop14 =
(decoder->InputWidth * decoder->InputAspect.num * 9) /
(decoder->InputAspect.den * 14);
crop14 = (decoder->InputHeight - crop14) / 2;
crop16 =
(decoder->InputWidth * decoder->InputAspect.num * 9) /
(decoder->InputAspect.den * 16);
crop16 = (decoder->InputHeight - crop16) / 2;
// -2 for rounding errors
if (decoder->AutoCrop->Y1 >= crop16 - 2
&& decoder->InputHeight - decoder->AutoCrop->Y2 >= crop16 - 2) {
next_state = 16;
} else if (decoder->AutoCrop->Y1 >= crop14 - 2
&& decoder->InputHeight - decoder->AutoCrop->Y2 >= crop14 - 2) {
next_state = 14;
} else {
next_state = 0;
}
if (decoder->AutoCrop->State == next_state) {
return;
}
Debug(3, "video: crop aspect %d:%d %d/%d %d+%d\n",
decoder->InputAspect.num, decoder->InputAspect.den, crop14, crop16,
decoder->AutoCrop->Y1, decoder->InputHeight - decoder->AutoCrop->Y2);
Debug(3, "video: crop aspect %d -> %d\n", decoder->AutoCrop->State,
next_state);
switch (decoder->AutoCrop->State) {
case 16:
case 14:
if (decoder->AutoCrop->Count++ < AutoCropDelay / 2) {
return;
}
break;
case 0:
if (decoder->AutoCrop->Count++ < AutoCropDelay) {
return;
}
break;
}
decoder->AutoCrop->Count = 0;
decoder->AutoCrop->State = next_state;
if (next_state) {
decoder->CropX = 0;
decoder->CropY = next_state == 16 ? crop16 : crop14;
decoder->CropWidth = decoder->InputWidth;
decoder->CropHeight = decoder->InputHeight - decoder->CropY * 2;
// FIXME: this overwrites user choosen output position
// FIXME: resize kills the auto crop values
decoder->OutputX = 0;
decoder->OutputY = 0;
decoder->OutputWidth = (VideoWindowHeight * next_state) / 9;
decoder->OutputHeight = (VideoWindowWidth * 9) / next_state;
if ((unsigned)decoder->OutputWidth > VideoWindowWidth) {
decoder->OutputWidth = VideoWindowWidth;
decoder->OutputY = (VideoWindowHeight - decoder->OutputHeight) / 2;
} else if ((unsigned)decoder->OutputHeight > VideoWindowHeight) {
decoder->OutputHeight = VideoWindowHeight;
decoder->OutputX = (VideoWindowWidth - decoder->OutputWidth) / 2;
}
Debug(3, "video: aspect output %dx%d %dx%d+%d+%d\n",
decoder->InputWidth, decoder->InputHeight, decoder->OutputWidth,
decoder->OutputHeight, decoder->OutputX, decoder->OutputY);
} else {
decoder->CropX = 0;
decoder->CropY = 0;
decoder->CropWidth = decoder->InputWidth;
decoder->CropHeight = decoder->InputHeight;
VdpauUpdateOutput(decoder);
}
}
#endif
/// ///
/// Queue output surface. /// Queue output surface.
/// ///
@ -5568,6 +5768,24 @@ static void VdpauMixVideo(VdpauDecoder * decoder)
#ifdef USE_GRAB #ifdef USE_GRAB
VdpauGrabSurface(decoder); VdpauGrabSurface(decoder);
#endif #endif
#ifdef USE_AUTOCROP
// reduce load, check only n frames
if (AutoCropInterval && !(decoder->FrameCounter % AutoCropInterval)) {
AVRational display_aspect_ratio;
av_reduce(&display_aspect_ratio.num, &display_aspect_ratio.den,
decoder->InputWidth * decoder->InputAspect.num,
decoder->InputHeight * decoder->InputAspect.den, 1024 * 1024);
// only 4:3 with 16:9/14:9 inside supported
if (display_aspect_ratio.num == 4 && display_aspect_ratio.den == 3) {
VdpauAutoCrop(decoder);
} else {
decoder->AutoCrop->Count = 0;
decoder->AutoCrop->State = 0;
}
}
#endif
if (decoder->Interlaced if (decoder->Interlaced
&& VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) { && VideoDeinterlace[decoder->Resolution] != VideoDeinterlaceWeave) {
@ -7481,6 +7699,25 @@ void VideoSetAudioDelay(int ms)
VideoAudioDelay = ms * 90; VideoAudioDelay = ms * 90;
} }
///
/// Set auto-crop parameters.
///
void VideoSetAutoCrop(int interval, int delay)
{
#ifdef USE_AUTOCROP
int i;
AutoCropInterval = interval;
AutoCropDelay = delay;
#ifdef USE_VDPAU
for (i = 0; i < VdpauDecoderN; ++i) {
VdpauDecoders[i]->AutoCrop->State = 0;
VdpauDecoders[i]->AutoCrop->Count = 0;
}
#endif
#endif
}
/// ///
/// Initialize video output module. /// Initialize video output module.
/// ///
@ -7659,7 +7896,7 @@ static void PrintVersion(void)
#ifdef GIT_REV #ifdef GIT_REV
"(GIT-" GIT_REV ")" "(GIT-" GIT_REV ")"
#endif #endif
",\n\t(c) 2009 - 2011 by Johns\n" ",\n\t(c) 2009 - 2012 by Johns\n"
"\tLicense AGPLv3: GNU Affero General Public License version 3\n"); "\tLicense AGPLv3: GNU Affero General Public License version 3\n");
} }

View File

@ -100,6 +100,9 @@ extern void VideoSetSharpen(int[]);
/// Set audio delay. /// Set audio delay.
extern void VideoSetAudioDelay(int); extern void VideoSetAudioDelay(int);
/// Set auto-crop parameters.
extern void VideoSetAutoCrop(int, int);
/// Clear OSD. /// Clear OSD.
extern void VideoOsdClear(void); extern void VideoOsdClear(void);