VDPAU: Add screenshot support.

This commit is contained in:
Johns 2012-01-20 21:46:22 +01:00
parent 5ba88bb822
commit e32857a27a
6 changed files with 218 additions and 29 deletions

View File

@ -2,6 +2,7 @@ User johns
Date:
Release Version 0.4.0
VDPAU: Add grab image support.
VDPAU: Add auto-crop support.
VDPAU: Changed OSD alpha calculation.
Fix bug: Used VideoSharpen for denoise settings.

View File

@ -791,6 +791,29 @@ int PlayVideo(const uint8_t * data, int size)
return size;
}
/**
** Grabs the currently visible screen image.
**
** @param size size of the returned data
** @param jpeg flag true, create JPEG data
** @param quality JPEG quality
** @param width number of horizontal pixels in the frame
** @param height number of vertical pixels in the frame
*/
uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
{
if (jpeg) {
(void)quality;
Error(_("softhddev: jpeg grabbing not supported\n"));
return NULL;
}
if (width != -1 && height != -1) {
Error(_("softhddev: scaling not supported\n"));
return NULL;
}
return VideoGrab(size, &width, &height);
}
//////////////////////////////////////////////////////////////////////////////
/**

View File

@ -46,6 +46,8 @@ extern "C"
extern int PlayVideo(const uint8_t *, int);
/// C plugin play TS video packet
extern void PlayTsVideo(const uint8_t *, int);
/// C plugin grab an image
extern uint8_t *GrabImage(int *, int, int, int, int);
/// C plugin set play mode
extern void SetPlayMode(void);

View File

@ -126,7 +126,7 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
csoft = new cSoftRemote(keymap);
}
dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
//dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
csoft->Put(key, repeat, release);
}
@ -295,8 +295,8 @@ void cSoftOsd::Flush(void)
h = pm->ViewPort().Height();
/*
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h, x,
y, pm->Data());
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h,
x, y, pm->Data());
*/
OsdDrawARGB(x, y, w, h, pm->Data());
@ -832,13 +832,22 @@ int cSoftHdDevice::PlayTsAudio(const uchar * data, int length)
#endif
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int sizex,
int sizey)
/**
** Grabs the currently visible screen image.
**
** @param size size of the returned data
** @param jpeg flag true, create JPEG data
** @param quality JPEG quality
** @param width number of horizontal pixels in the frame
** @param height number of vertical pixels in the frame
*/
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
int height)
{
dsyslog("[softhddev]%s: %d, %d, %d, %dx%d\n", __FUNCTION__, size, jpeg,
quality, sizex, sizey);
quality, width, height);
return NULL;
return ::GrabImage(&size, jpeg, quality, width, height);
}
//////////////////////////////////////////////////////////////////////////////

193
video.c
View File

@ -38,7 +38,7 @@
#define USE_XLIB_XCB ///< use xlib/xcb backend
#define USE_AUTOCROP ///< compile autocrop support
#define noUSE_GRAB ///< experimental grab code
#define USE_GRAB ///< experimental grab code
#define noUSE_GLX ///< outdated GLX code
#define noUSE_DOUBLEBUFFER ///< use GLX double buffers
@ -194,6 +194,19 @@ typedef enum _video_zoom_modes_
VideoAnamorphic, ///< anamorphic scaled (unsupported)
} VideoZoomModes;
///
/// Video output module structure and typedef.
///
typedef struct _video_module_
{
const char *Name; ///< video output module name
void (*const Thread) (void); ///< module thread handler
void (*const Init) (const char *); ///< initialize video output module
void (*const Exit) (void); ///< cleanup video output module
} VideoModule;
//----------------------------------------------------------------------------
// Defines
//----------------------------------------------------------------------------
@ -227,6 +240,8 @@ static int VideoWindowY; ///< video outout window y coordinate
static unsigned VideoWindowWidth; ///< video output window width
static unsigned VideoWindowHeight; ///< video output window height
static const VideoModule *VideoUsedModule; ///< selected video module
static char VideoHardwareDecoder; ///< flag use hardware decoder
static char VideoSurfaceModesChanged; ///< flag surface modes changed
@ -3697,6 +3712,15 @@ static void VaapiOsdExit(void)
}
}
///
/// VA-API module.
///
static const VideoModule VaapiModule = {
.Name = "va-api",
.Init = VideoVaapiInit,
.Exit = VideoVaapiExit,
};
#endif
//----------------------------------------------------------------------------
@ -3829,7 +3853,8 @@ static VdpOutputSurfaceQueryCapabilities *VdpauOutputSurfaceQueryCapabilities;
static VdpOutputSurfaceCreate *VdpauOutputSurfaceCreate;
static VdpOutputSurfaceDestroy *VdpauOutputSurfaceDestroy;
static VdpOutputSurfaceGetParameters *VdpauOutputSurfaceGetParameters;
static VdpOutputSurfaceGetBitsNative *VdpauOutputSurfaceGetBitsNative;
static VdpOutputSurfacePutBitsNative *VdpauOutputSurfacePutBitsNative;
static VdpBitmapSurfaceQueryCapabilities *VdpauBitmapSurfaceQueryCapabilities;
@ -4571,10 +4596,10 @@ static void VideoVdpauInit(const char *display_name)
"OutputSurfaceCreate");
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY,
&VdpauOutputSurfaceDestroy, "OutputSurfaceDestroy");
#if 0
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS, &, "");
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE, &, "");
#endif
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_GET_PARAMETERS,
&VdpauOutputSurfaceGetParameters, "OutputSurfaceGetParameters");
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE,
&VdpauOutputSurfaceGetBitsNative, "OutputSurfaceGetBitsNative");
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE,
&VdpauOutputSurfacePutBitsNative, "OutputSurfacePutBitsNative");
#if 0
@ -5210,7 +5235,7 @@ static void VdpauSetup(VdpauDecoder * decoder,
///
/// @param decoder VDPAU hw decoder
///
static void VdpauGrabSurface(VdpauDecoder * decoder)
static void VdpauGrabVideoSurface(VdpauDecoder * decoder)
{
VdpVideoSurface surface;
VdpStatus status;
@ -5270,6 +5295,87 @@ static void VdpauGrabSurface(VdpauDecoder * decoder)
free(base);
}
///
/// Grab output surface.
///
/// @param decoder VDPAU hw decoder
///
static uint8_t *VdpauGrabOutputSurface(int *ret_size, int *ret_width,
int *ret_height)
{
VdpOutputSurface surface;
VdpStatus status;
VdpRGBAFormat rgba_format;
uint32_t size;
uint32_t width;
uint32_t height;
void *base;
void *data[1];
uint32_t pitches[1];
VdpRect source_rect;
// FIXME: test function to grab output surface content
surface = VdpauSurfacesRb[VdpauSurfaceIndex];
// get real surface size
status =
VdpauOutputSurfaceGetParameters(surface, &rgba_format, &width,
&height);
if (status != VDP_STATUS_OK) {
Error(_("video/vdpau: can't get output surface parameters: %s\n"),
VdpauGetErrorString(status));
return NULL;
}
Debug(3, "video/vdpau: grab %dx%d format %d\n", width, height,
rgba_format);
switch (rgba_format) {
case VDP_RGBA_FORMAT_B8G8R8A8:
case VDP_RGBA_FORMAT_R8G8B8A8:
size = width * height * sizeof(uint32_t);
base = malloc(size);
if (!base) {
Error(_("video/vdpau: out of memory\n"));
return NULL;
}
pitches[0] = width * sizeof(uint32_t);
data[0] = base;
break;
case VDP_RGBA_FORMAT_R10G10B10A2:
case VDP_RGBA_FORMAT_B10G10R10A2:
case VDP_RGBA_FORMAT_A8:
Error(_("video/vdpau: unsupported rgba format %d\n"), rgba_format);
return NULL;
}
source_rect.x0 = 0;
source_rect.y0 = 0;
source_rect.x1 = source_rect.x0 + width;
source_rect.y1 = source_rect.y0 + height;
status =
VdpauOutputSurfaceGetBitsNative(surface, &source_rect, data, pitches);
if (status != VDP_STATUS_OK) {
Error(_("video/vdpau: can't get video surface bits native: %s\n"),
VdpauGetErrorString(status));
free(base);
return NULL;
}
if (ret_size) {
*ret_size = size;
}
if (ret_width) {
*ret_width = width;
}
if (ret_height) {
*ret_height = height;
}
return base;
}
#endif
#ifdef USE_AUTOCROP
@ -5765,9 +5871,6 @@ 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
#ifdef USE_AUTOCROP
// reduce load, check only n frames
if (AutoCropInterval && !(decoder->FrameCounter % AutoCropInterval)) {
@ -6497,6 +6600,15 @@ static void VdpauOsdExit(void)
#endif
}
///
/// VDPAU module.
///
static const VideoModule VdpauModule = {
.Name = "vdpau",
.Init = VideoVdpauInit,
.Exit = VideoVdpauExit,
};
#endif
//----------------------------------------------------------------------------
@ -7377,6 +7489,48 @@ int64_t VideoGetClock(void)
return 0L;
}
///
/// Grab full screen image.
///
uint8_t *VideoGrab(int *size, int *width, int *height)
{
Debug(3, "video: grab\n");
#ifdef USE_GRAB
#ifdef USE_VDPAU
if (VideoVdpauEnabled) {
uint8_t *data;
uint8_t *rgb;
char buf[64];
int i;
int n;
data = VdpauGrabOutputSurface(size, width, height);
n = snprintf(buf, sizeof(buf), "P6\n%d\n%d\n255\n", *width, *height);
rgb = malloc(*width * *height * 3 + n);
if (!rgb) {
Error(_("video: out of memory\n"));
free(data);
return NULL;
}
memcpy(rgb, buf, n); // header
for (i = 0; i < *size / 4; ++i) { // convert bgra -> rgb
rgb[n + i * 3 + 0] = data[i * 4 + 2];
rgb[n + i * 3 + 1] = data[i * 4 + 1];
rgb[n + i * 3 + 2] = data[i * 4 + 0];
}
free(data);
*size = *width * *height * 3 + n;
return rgb;
}
#endif
#endif
return NULL;
}
//----------------------------------------------------------------------------
// Setup
//----------------------------------------------------------------------------
@ -7818,17 +7972,21 @@ void VideoInit(const char *display_name)
#ifdef USE_VDPAU
if (VideoVdpauEnabled) {
VideoVdpauInit(display_name);
if (VideoVdpauEnabled) {
VideoUsedModule = &VdpauModule;
#ifdef USE_VAAPI
// disable va-api, if vdpau succeeded
if (VideoVdpauEnabled) {
VideoVaapiEnabled = 0;
}
#endif
}
}
#endif
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
VideoVaapiInit(display_name);
if (VideoVaapiEnabled) {
VideoUsedModule = &VaapiModule;
}
}
#endif
@ -7851,16 +8009,9 @@ void VideoExit(void)
#ifdef USE_VIDEO_THREAD
VideoThreadExit();
#endif
#ifdef USE_VDPAU
if (VideoVdpauEnabled) {
VideoVdpauExit();
if (VideoUsedModule) {
VideoUsedModule->Exit();
}
#endif
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
VideoVaapiExit();
}
#endif
#ifdef USE_GLX
if (GlxEnabled) {
GlxExit();

View File

@ -114,6 +114,9 @@ extern void VideoGetOsdSize(int *, int *);
extern int64_t VideoGetClock(void); ///< Get video clock.
/// Grab screen.
extern uint8_t *VideoGrab(int *, int *, int *);
extern void VideoOsdInit(void); ///< Setup osd.
extern void VideoOsdExit(void); ///< Cleanup osd.