summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--softhddev.c23
-rw-r--r--softhddev.h2
-rw-r--r--softhddevice.cpp23
-rw-r--r--video.c195
-rw-r--r--video.h3
6 files changed, 218 insertions, 29 deletions
diff --git a/ChangeLog b/ChangeLog
index 576fc6a..dab8a51 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/softhddev.c b/softhddev.c
index 267b603..4ddf06c 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -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);
+}
+
//////////////////////////////////////////////////////////////////////////////
/**
diff --git a/softhddev.h b/softhddev.h
index 51e07ba..a1e21e3 100644
--- a/softhddev.h
+++ b/softhddev.h
@@ -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);
diff --git a/softhddevice.cpp b/softhddevice.cpp
index 2e5ef41..cbfd242 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -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);
}
//////////////////////////////////////////////////////////////////////////////
diff --git a/video.c b/video.c
index 6fb1fb2..27bdb43 100644
--- a/video.c
+++ b/video.c
@@ -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);
-#ifdef USE_VAAPI
- // disable va-api, if vdpau succeeded
if (VideoVdpauEnabled) {
+ VideoUsedModule = &VdpauModule;
+#ifdef USE_VAAPI
+ // disable va-api, if vdpau succeeded
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();
- }
-#endif
-#ifdef USE_VAAPI
- if (VideoVaapiEnabled) {
- VideoVaapiExit();
+ if (VideoUsedModule) {
+ VideoUsedModule->Exit();
}
-#endif
#ifdef USE_GLX
if (GlxEnabled) {
GlxExit();
diff --git a/video.h b/video.h
index f3ff6ad..c6c3bc6 100644
--- a/video.h
+++ b/video.h
@@ -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.