summaryrefslogtreecommitdiff
path: root/video.c
diff options
context:
space:
mode:
Diffstat (limited to 'video.c')
-rw-r--r--video.c162
1 files changed, 145 insertions, 17 deletions
diff --git a/video.c b/video.c
index 7e3003d..75aca6c 100644
--- a/video.c
+++ b/video.c
@@ -5079,6 +5079,10 @@ static VdpOutputSurface VdpauOsdOutputSurface[2] = {
#endif
static int VdpauOsdSurfaceIndex; ///< index into double buffered osd
+ /// grab render output surface
+static VdpOutputSurface VdpauGrabRenderSurface = VDP_INVALID_HANDLE;
+static pthread_mutex_t VdpauGrabMutex;
+
///
/// Function pointer of the VDPAU device.
///
@@ -5807,6 +5811,7 @@ static inline void VdpauGetProc(const VdpFuncId id, void *addr,
static void VdpauInitOutputQueue(void)
{
VdpStatus status;
+ VdpRGBAFormat format;
int i;
status =
@@ -5839,12 +5844,10 @@ static void VdpauInitOutputQueue(void)
//
// Create display output surfaces
//
+ format = VDP_RGBA_FORMAT_B8G8R8A8;
+ // FIXME: does a 10bit rgba produce a better output?
+ // format = VDP_RGBA_FORMAT_R10G10B10A2;
for (i = 0; i < OUTPUT_SURFACES_MAX; ++i) {
- VdpRGBAFormat format;
-
- format = VDP_RGBA_FORMAT_B8G8R8A8;
- // FIXME: does a 10bit rgba produce a better output?
- // format = VDP_RGBA_FORMAT_R10G10B10A2;
status =
VdpauOutputSurfaceCreate(VdpauDevice, format, VideoWindowWidth,
VideoWindowHeight, VdpauSurfacesRb + i);
@@ -5855,6 +5858,20 @@ static void VdpauInitOutputQueue(void)
Debug(3, "video/vdpau: created output surface %dx%d with id 0x%08x\n",
VideoWindowWidth, VideoWindowHeight, VdpauSurfacesRb[i]);
}
+
+ //
+ // Create render output surface for grabbing
+ //
+ status =
+ VdpauOutputSurfaceCreate(VdpauDevice, format, VideoWindowWidth,
+ VideoWindowHeight, &VdpauGrabRenderSurface);
+ if (status != VDP_STATUS_OK) {
+ Fatal(_("video/vdpau: can't create grab render output surface: %s\n"),
+ VdpauGetErrorString(status));
+ }
+ Debug(3,
+ "video/vdpau: created grab render output surface %dx%d with id 0x%08x\n",
+ VideoWindowWidth, VideoWindowHeight, VdpauGrabRenderSurface);
}
///
@@ -5863,13 +5880,12 @@ static void VdpauInitOutputQueue(void)
static void VdpauExitOutputQueue(void)
{
int i;
+ VdpStatus status;
//
// destroy display output surfaces
//
for (i = 0; i < OUTPUT_SURFACES_MAX; ++i) {
- VdpStatus status;
-
Debug(4, "video/vdpau: destroy output surface with id 0x%08x\n",
VdpauSurfacesRb[i]);
if (VdpauSurfacesRb[i] != VDP_INVALID_HANDLE) {
@@ -5881,6 +5897,15 @@ static void VdpauExitOutputQueue(void)
VdpauSurfacesRb[i] = VDP_INVALID_HANDLE;
}
}
+ if (VdpauGrabRenderSurface != VDP_INVALID_HANDLE) {
+ status = VdpauOutputSurfaceDestroy(VdpauGrabRenderSurface);
+ if (status != VDP_STATUS_OK) {
+ Error(_
+ ("video/vdpau: can't destroy grab render output surface: %s\n"),
+ VdpauGetErrorString(status));
+ }
+ VdpauGrabRenderSurface = VDP_INVALID_HANDLE;
+ }
if (VdpauQueue) {
VdpauPresentationQueueDestroy(VdpauQueue);
VdpauQueue = 0;
@@ -5927,6 +5952,8 @@ static int VdpauInit(const char *display_name)
uint32_t max_width;
uint32_t max_height;
+ pthread_mutex_init(&VdpauGrabMutex, NULL);
+
status =
vdp_device_create_x11(XlibDisplay, DefaultScreen(XlibDisplay),
&VdpauDevice, &VdpauGetProcAddress);
@@ -6358,6 +6385,8 @@ static void VdpauExit(void)
}
VdpauDevice = 0;
}
+
+ pthread_mutex_destroy(&VdpauGrabMutex);
}
///
@@ -6684,13 +6713,13 @@ static void VdpauGrabVideoSurface(VdpauDecoder * decoder)
#endif
///
-/// Grab output surface.
+/// Grab output surface already locked.
///
/// @param ret_size[out] size of allocated surface copy
/// @param ret_width[in,out] width of output
/// @param ret_height[in,out] height of output
///
-static uint8_t *VdpauGrabOutputSurface(int *ret_size, int *ret_width,
+static uint8_t *VdpauGrabOutputSurfaceLocked(int *ret_size, int *ret_width,
int *ret_height)
{
VdpOutputSurface surface;
@@ -6703,8 +6732,7 @@ static uint8_t *VdpauGrabOutputSurface(int *ret_size, int *ret_width,
void *data[1];
uint32_t pitches[1];
VdpRect source_rect;
-
- // FIXME: test function to grab output surface content
+ VdpRect output_rect;
surface = VdpauSurfacesRb[VdpauSurfaceIndex];
@@ -6721,8 +6749,62 @@ static uint8_t *VdpauGrabOutputSurface(int *ret_size, int *ret_width,
Debug(3, "video/vdpau: grab %dx%d format %d\n", width, height,
rgba_format);
- // FIXME: scale surface to requested size with
- // VdpauOutputSurfaceRenderOutputSurface
+ source_rect.x0 = 0;
+ source_rect.y0 = 0;
+ source_rect.x1 = width;
+ source_rect.y1 = height;
+
+ if (ret_width && ret_height) {
+ if (*ret_width <= -64) { // this is a Atmo grab service request
+ int overscan;
+
+ // calculate aspect correct size of analyze image
+ width = *ret_width * -1;
+ height = (width * source_rect.y1) / source_rect.x1;
+
+ // calculate size of grab (sub) window
+ overscan = *ret_height;
+
+ if (overscan > 0 && overscan <= 200) {
+ source_rect.x0 = source_rect.x1 * overscan / 1000;
+ source_rect.x1 -= source_rect.x0;
+ source_rect.y0 = source_rect.y1 * overscan / 1000;
+ source_rect.y1 -= source_rect.y0;
+ }
+ } else {
+ if (*ret_width > 0 && (unsigned)*ret_width < width) {
+ width = *ret_width;
+ }
+ if (*ret_height > 0 && (unsigned)*ret_height < height) {
+ height = *ret_height;
+ }
+ }
+
+ Debug(3, "video/vdpau: grab source rect %d,%d:%d,%d dest dim %dx%d\n",
+ source_rect.x0, source_rect.y0, source_rect.x1, source_rect.y1,
+ width, height);
+
+ if ((source_rect.x1 - source_rect.x0) != width
+ || (source_rect.y1 - source_rect.y0) != height) {
+ output_rect.x0 = 0;
+ output_rect.y0 = 0;
+ output_rect.x1 = width;
+ output_rect.y1 = height;
+
+ status =
+ VdpauOutputSurfaceRenderOutputSurface(VdpauGrabRenderSurface,
+ &output_rect, surface, &source_rect, NULL, NULL,
+ VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't render output surface: %s\n"),
+ VdpauGetErrorString(status));
+ return NULL;
+ }
+
+ surface = VdpauGrabRenderSurface;
+ source_rect = output_rect;
+ }
+ }
switch (rgba_format) {
case VDP_RGBA_FORMAT_B8G8R8A8:
@@ -6744,10 +6826,6 @@ static uint8_t *VdpauGrabOutputSurface(int *ret_size, int *ret_width,
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) {
@@ -6770,6 +6848,28 @@ static uint8_t *VdpauGrabOutputSurface(int *ret_size, int *ret_width,
return base;
}
+///
+/// Grab output surface.
+///
+/// @param ret_size[out] size of allocated surface copy
+/// @param ret_width[in,out] width of output
+/// @param ret_height[in,out] height of output
+///
+static uint8_t *VdpauGrabOutputSurface(int *ret_size, int *ret_width,
+ int *ret_height)
+{
+ uint8_t *img;
+
+ if (VdpauGrabRenderSurface == VDP_INVALID_HANDLE) {
+ return NULL; // vdpau video module not yet initialized
+ }
+
+ pthread_mutex_lock(&VdpauGrabMutex);
+ img = VdpauGrabOutputSurfaceLocked(ret_size, ret_width, ret_height);
+ pthread_mutex_unlock(&VdpauGrabMutex);
+ return img;
+}
+
#endif
#ifdef USE_AUTOCROP
@@ -9264,6 +9364,8 @@ uint8_t *VideoGrab(int *size, int *width, int *height, int write_header)
scale_height = *height;
n = 0;
data = VideoUsedModule->GrabOutput(size, width, height);
+ if (data == NULL)
+ return NULL;
if (scale_width <= 0) {
scale_width = *width;
@@ -9350,6 +9452,32 @@ uint8_t *VideoGrab(int *size, int *width, int *height, int write_header)
return NULL;
}
+///
+/// Grab image service.
+///
+/// @param size[out] size of allocated image
+/// @param width[in,out] width of image
+/// @param height[in,out] height of image
+///
+uint8_t *VideoGrabService(int *size, int *width, int *height)
+{
+ Debug(3, "video: grab service\n");
+
+#ifdef USE_GRAB
+ if (VideoUsedModule->GrabOutput) {
+ return VideoUsedModule->GrabOutput(size, width, height);
+ } else
+#endif
+ {
+ Warning(_("softhddev: grab unsupported\n"));
+ }
+
+ (void)size;
+ (void)width;
+ (void)height;
+ return NULL;
+}
+
#ifdef USE_SCREENSAVER
//----------------------------------------------------------------------------