summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--Todo1
-rw-r--r--softhddevice.cpp50
-rw-r--r--softhddevice_service.h44
-rw-r--r--video.c162
-rw-r--r--video.h3
6 files changed, 242 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index cd14662..b2abb88 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,15 @@ User johns
Date:
Release Version 0.5.1
+
+User durchflieger
+Date: Mon Apr 30 14:46:51 CEST 2012
+
+ Adds VDR DFAtmo Plugin support.
+
+User johns
+Date: Mon Apr 30 13:56:26 CEST 2012
+
Fix bug: don't normalize or compress pass-through samples.
Make audio ring buffer size a multiple of 3,5,7,8.
Add reset ring buffer support.
diff --git a/Todo b/Todo
index a36b976..e8de19f 100644
--- a/Todo
+++ b/Todo
@@ -121,7 +121,6 @@ future features (not planed for 1.0 - 1.5)
video out with opengl
video out with xvba
software decoder for xv / opengl
- atmolight support
multistream handling
pip support
save and use auto-crop with channel zapping
diff --git a/softhddevice.cpp b/softhddevice.cpp
index 7a07e53..e2ab45f 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -33,6 +33,7 @@
#include "softhddev.h"
#include "softhddevice.h"
+#include "softhddevice_service.h"
extern "C"
{
#include "audio.h"
@@ -693,8 +694,8 @@ void cMenuSetupSoft::Create(void)
if (Audio) {
Add(new cMenuEditIntItem(tr("Audio/Video delay (ms)"), &AudioDelay,
-1000, 1000));
- Add(new cMenuEditStraItem(tr("Audio drift correction"),
- &AudioDrift, 4, audiodrift));
+ Add(new cMenuEditStraItem(tr("Audio drift correction"), &AudioDrift, 4,
+ audiodrift));
Add(new cMenuEditStraItem(tr("Audio pass-through"), &AudioPassthrough,
2, passthrough));
Add(new cMenuEditBoolItem(tr("Enable AC-3 downmix"), &AudioDownmix,
@@ -1720,7 +1721,7 @@ class cPluginSoftHdDevice:public cPlugin
virtual cOsdObject *MainMenuAction(void);
virtual cMenuSetupPage *SetupMenu(void);
virtual bool SetupParse(const char *, const char *);
-// virtual bool Service(const char *, void * = NULL);
+ virtual bool Service(const char *, void * = NULL);
virtual const char **SVDRPHelpPages(void);
virtual cString SVDRPCommand(const char *, const char *, int &);
};
@@ -2074,17 +2075,48 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return false;
}
-#if 0
-
-bool cPluginSoftHdDevice::Service(const char *Id, void *Data)
+/**
+** Receive requests or messages.
+**
+** @param id unique identification string that identifies the
+** service protocol
+** @param data custom data structure
+*/
+bool cPluginSoftHdDevice::Service(const char *id, void *data)
{
- dsyslog("[softhddev]%s:\n", __FUNCTION__);
+ dsyslog("[softhddev]%s: id %s\n", __FUNCTION__, id);
+
+ if (strcmp(id, ATMO_GRAB_SERVICE) == 0) {
+ int width;
+ int height;
+
+ if (data == NULL) {
+ return true;
+ }
+
+ SoftHDDevice_AtmoGrabService_v1_0_t *r =
+ (SoftHDDevice_AtmoGrabService_v1_0_t *) data;
+ if (r->structSize != sizeof(SoftHDDevice_AtmoGrabService_v1_0_t)
+ || r->analyseSize < 64 || r->analyseSize > 256
+ || r->clippedOverscan < 0 || r->clippedOverscan > 200) {
+ return false;
+ }
+
+ width = r->analyseSize * -1; // Internal marker for Atmo grab service
+ height = r->clippedOverscan;
+ r->img = VideoGrabService(&r->imgSize, &width, &height);
+ if (r->img == NULL) {
+ return false;
+ }
+ r->imgType = GRAB_IMG_RGBA_FORMAT_B8G8R8A8;
+ r->width = width;
+ r->height = height;
+ return true;
+ }
return false;
}
-#endif
-
//----------------------------------------------------------------------------
// cPlugin SVDRP
//----------------------------------------------------------------------------
diff --git a/softhddevice_service.h b/softhddevice_service.h
new file mode 100644
index 0000000..737f8b0
--- /dev/null
+++ b/softhddevice_service.h
@@ -0,0 +1,44 @@
+///
+/// @file softhddev_service.h @brief software HD device service header file.
+///
+/// Copyright (c) 2012 by durchflieger. All Rights Reserved.
+///
+/// Contributor(s):
+///
+/// License: AGPLv3
+///
+/// This program is free software: you can redistribute it and/or modify
+/// it under the terms of the GNU Affero General Public License as
+/// published by the Free Software Foundation, either version 3 of the
+/// License.
+///
+/// This program is distributed in the hope that it will be useful,
+/// but WITHOUT ANY WARRANTY; without even the implied warranty of
+/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+/// GNU Affero General Public License for more details.
+///
+/// $Id$
+//////////////////////////////////////////////////////////////////////////////
+
+#pragma once
+
+#define ATMO_GRAB_SERVICE "SoftHDDevice-AtmoGrabService-v1.0"
+
+enum
+{ GRAB_IMG_RGBA_FORMAT_B8G8R8A8 };
+
+typedef struct
+{
+ int structSize;
+
+ // request data
+ int analyseSize;
+ int clippedOverscan;
+
+ // reply data
+ int imgType;
+ int imgSize;
+ int width;
+ int height;
+ void *img;
+} SoftHDDevice_AtmoGrabService_v1_0_t;
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
//----------------------------------------------------------------------------
diff --git a/video.h b/video.h
index 2be1e5d..1793e29 100644
--- a/video.h
+++ b/video.h
@@ -168,6 +168,9 @@ extern void VideoSetTrickSpeed(VideoHwDecoder *, int);
/// Grab screen.
extern uint8_t *VideoGrab(int *, int *, int *, int);
+ /// Grab screen raw.
+extern uint8_t *VideoGrabService(int *, int *, int *);
+
extern void VideoOsdInit(void); ///< Setup osd.
extern void VideoOsdExit(void); ///< Cleanup osd.