summaryrefslogtreecommitdiff
path: root/video.c
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2012-01-18 15:15:37 +0100
committerJohns <johns98@gmx.net>2012-01-18 15:15:37 +0100
commitc6e66e0787f62fdf74dde43dcc88818f80b7334e (patch)
tree20cd574eb4c2aa096a9788513b63fe41cdd3b45e /video.c
parent19d4eeed8268c88feff69f06218a11e68e548246 (diff)
downloadvdr-plugin-softhddevice-c6e66e0787f62fdf74dde43dcc88818f80b7334e.tar.gz
vdr-plugin-softhddevice-c6e66e0787f62fdf74dde43dcc88818f80b7334e.tar.bz2
OSD improvements:
Use OSD size equal to video window. Update only dirty area(s) of OSD. Show/mix only used area of OSD. Fix bug: vpdau use previous resolution for deint, ...
Diffstat (limited to 'video.c')
-rw-r--r--video.c446
1 files changed, 321 insertions, 125 deletions
diff --git a/video.c b/video.c
index 85b7beb..41351d9 100644
--- a/video.c
+++ b/video.c
@@ -25,7 +25,7 @@
///
/// This module contains all video rendering functions.
///
-/// @todo hide mouse cursor support
+/// @todo disable screen saver support
///
/// Uses Xlib where it is needed for VA-API or vdpau. XCB is used for
/// everything else.
@@ -36,16 +36,16 @@
/// - Xrender rendering
///
-#define USE_XLIB_XCB
-#define noUSE_GRAB
-#define noUSE_GLX
-#define noUSE_DOUBLEBUFFER
+#define USE_XLIB_XCB ///< use xlib/xcb backend
+#define noUSE_GRAB ///< experimental grab code
+#define noUSE_GLX ///< outdated GLX code
+#define noUSE_DOUBLEBUFFER ///< use GLX double buffers
//#define USE_VAAPI ///< enable vaapi support
//#define USE_VDPAU ///< enable vdpau support
#define noUSE_BITMAP ///< use vdpau bitmap surface
-#define USE_VIDEO_THREAD
+#define USE_VIDEO_THREAD ///< run decoder in an own thread
#include <sys/time.h>
#include <sys/shm.h>
@@ -275,6 +275,14 @@ static pthread_mutex_t VideoLockMutex; ///< video lock mutex
#endif
+static char OsdShown; ///< flag show osd
+static int OsdWidth; ///< osd width
+static int OsdHeight; ///< osd height
+static int OsdDirtyX; ///< osd dirty area x
+static int OsdDirtyY; ///< osd dirty area y
+static int OsdDirtyWidth; ///< osd dirty area width
+static int OsdDirtyHeight; ///< osd dirty area height
+
//----------------------------------------------------------------------------
// Functions
//----------------------------------------------------------------------------
@@ -863,8 +871,9 @@ static void AutoCropDetect(int width, int height, void *data[3],
{
const void *data_y;
unsigned length_y;
- int x;
- int y;
+
+ //int x;
+ //int y;
int x1;
int x2;
int y1;
@@ -1010,52 +1019,59 @@ static void VaapiDestroyDeinterlaceImages(VaapiDecoder *);
// Surfaces -------------------------------------------------------------
///
-/// Create surfaces for VA-API decoder.
+/// Associate OSD with surface.
///
/// @param decoder VA-API decoder
/// @param width surface source/video width
/// @param height surface source/video height
///
-static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
+static void VaapiAssociate(VaapiDecoder * decoder, int width, int height)
{
-#ifdef DEBUG
- if (!decoder->SurfacesNeeded) {
- Error(_("video/vaapi: surface needed not set\n"));
- decoder->SurfacesNeeded = 3 + VIDEO_SURFACES_MAX;
- }
-#endif
- Debug(3, "video/vaapi: %s: %dx%d * %d\n", __FUNCTION__, width, height,
- decoder->SurfacesNeeded);
+ int x;
+ int y;
+ int w;
+ int h;
- decoder->SurfaceFreeN = decoder->SurfacesNeeded;
- // VA_RT_FORMAT_YUV420 VA_RT_FORMAT_YUV422 VA_RT_FORMAT_YUV444
- if (vaCreateSurfaces(decoder->VaDisplay, width, height,
- VA_RT_FORMAT_YUV420, decoder->SurfaceFreeN,
- decoder->SurfacesFree) != VA_STATUS_SUCCESS) {
- Fatal(_("video/vaapi: can't create %d surfaces\n"),
- decoder->SurfaceFreeN);
- // FIXME: write error handler / fallback
- }
- //
- // update OSD associate
- //
if (VaOsdSubpicture == VA_INVALID_ID) {
Warning(_("video/vaapi: no osd subpicture yet\n"));
return;
}
+
+ x = 0;
+ y = 0;
+ w = VaOsdImage.width;
+ h = VaOsdImage.height;
+
// FIXME: associate only if osd is displayed
if (VaapiUnscaledOsd) {
- if (vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
- decoder->SurfacesFree, decoder->SurfaceFreeN, 0, 0,
- VaOsdImage.width, VaOsdImage.height, 0, 0, VideoWindowWidth,
- VideoWindowHeight, VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD)
+ if (decoder->SurfaceFreeN
+ && vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
+ decoder->SurfacesFree, decoder->SurfaceFreeN, x, y, w, h, 0, 0,
+ VideoWindowWidth, VideoWindowHeight,
+ VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't associate subpicture\n"));
+ }
+ if (decoder->SurfaceUsedN
+ && vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
+ decoder->SurfacesUsed, decoder->SurfaceUsedN, x, y, w, h, 0, 0,
+ VideoWindowWidth, VideoWindowHeight,
+ VA_SUBPICTURE_DESTINATION_IS_SCREEN_COORD)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't associate subpicture\n"));
}
} else {
- if (vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
- decoder->SurfacesFree, decoder->SurfaceFreeN, 0, 0,
- VaOsdImage.width, VaOsdImage.height, 0, 0, width, height, 0)
+ if (decoder->SurfaceFreeN
+ && vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
+ decoder->SurfacesFree, decoder->SurfaceFreeN, x, y, w, h, 0, 0,
+ width, height, 0)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't associate subpicture\n"));
+ }
+ if (decoder->SurfaceUsedN
+ && vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
+ decoder->SurfacesUsed, decoder->SurfaceUsedN, x, y, w, h, 0, 0,
+ width, height, 0)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't associate subpicture\n"));
}
@@ -1063,17 +1079,12 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
}
///
-/// Destroy surfaces of VA-API decoder.
+/// Deassociate OSD with surface.
///
/// @param decoder VA-API decoder
///
-static void VaapiDestroySurfaces(VaapiDecoder * decoder)
+static void VaapiDeassociate(VaapiDecoder * decoder)
{
- Debug(3, "video/vaapi: %s:\n", __FUNCTION__);
-
- //
- // update OSD associate
- //
if (VaOsdSubpicture != VA_INVALID_ID) {
if (decoder->SurfaceFreeN
&& vaDeassociateSubpicture(VaDisplay, VaOsdSubpicture,
@@ -1091,6 +1102,54 @@ static void VaapiDestroySurfaces(VaapiDecoder * decoder)
decoder->SurfaceUsedN);
}
}
+}
+
+///
+/// Create surfaces for VA-API decoder.
+///
+/// @param decoder VA-API decoder
+/// @param width surface source/video width
+/// @param height surface source/video height
+///
+static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
+{
+#ifdef DEBUG
+ if (!decoder->SurfacesNeeded) {
+ Error(_("video/vaapi: surface needed not set\n"));
+ decoder->SurfacesNeeded = 3 + VIDEO_SURFACES_MAX;
+ }
+#endif
+ Debug(3, "video/vaapi: %s: %dx%d * %d\n", __FUNCTION__, width, height,
+ decoder->SurfacesNeeded);
+
+ decoder->SurfaceFreeN = decoder->SurfacesNeeded;
+ // VA_RT_FORMAT_YUV420 VA_RT_FORMAT_YUV422 VA_RT_FORMAT_YUV444
+ if (vaCreateSurfaces(decoder->VaDisplay, width, height,
+ VA_RT_FORMAT_YUV420, decoder->SurfaceFreeN,
+ decoder->SurfacesFree) != VA_STATUS_SUCCESS) {
+ Fatal(_("video/vaapi: can't create %d surfaces\n"),
+ decoder->SurfaceFreeN);
+ // FIXME: write error handler / fallback
+ }
+ //
+ // update OSD associate
+ //
+ VaapiAssociate(decoder, width, height);
+}
+
+///
+/// Destroy surfaces of VA-API decoder.
+///
+/// @param decoder VA-API decoder
+///
+static void VaapiDestroySurfaces(VaapiDecoder * decoder)
+{
+ Debug(3, "video/vaapi: %s:\n", __FUNCTION__);
+
+ //
+ // update OSD associate
+ //
+ VaapiDeassociate(decoder);
if (vaDestroySurfaces(decoder->VaDisplay, decoder->SurfacesFree,
decoder->SurfaceFreeN)
@@ -1525,23 +1584,6 @@ static void VideoVaapiExit(void)
}
VaapiDecoderN = 0;
- if (VaOsdImage.image_id != VA_INVALID_ID) {
- if (vaDestroyImage(VaDisplay,
- VaOsdImage.image_id) != VA_STATUS_SUCCESS) {
- Error(_("video/vaapi: can't destroy image!\n"));
- }
- VaOsdImage.image_id = VA_INVALID_ID;
- }
-
- if (VaOsdSubpicture != VA_INVALID_ID) {
- // still has 35 surfaces associated to it
- if (vaDestroySubpicture(VaDisplay, VaOsdSubpicture)
- != VA_STATUS_SUCCESS) {
- Error(_("video/vaapi: can't destroy subpicture\n"));
- }
- VaOsdSubpicture = VA_INVALID_ID;
- }
-
if (!VaDisplay) {
vaTerminate(VaDisplay);
VaDisplay = NULL;
@@ -3384,8 +3426,20 @@ static void VaapiOsdClear(void)
Error(_("video/vaapi: can't map osd image buffer\n"));
return;
}
- // 100% transparent
- memset(image_buffer, 0x00, VaOsdImage.data_size);
+ // have dirty area.
+ if (OsdDirtyWidth && OsdDirtyHeight) {
+ int o;
+
+ Debug(3, "video/vaapi: handle osd dirty area\n");
+ for (o = 0; o < OsdDirtyHeight; ++o) {
+ memset(image_buffer + (OsdDirtyX + (o +
+ OsdDirtyY) * VaOsdImage.width) * 4, 0,
+ OsdDirtyWidth * 4);
+ }
+ } else {
+ // 100% transparent
+ memset(image_buffer, 0x00, VaOsdImage.data_size);
+ }
if (vaUnmapBuffer(VaDisplay, VaOsdImage.buf) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't unmap osd image buffer\n"));
@@ -3406,6 +3460,8 @@ static void VaapiOsdClear(void)
static void VaapiUploadImage(int x, int y, int width, int height,
const uint8_t * argb)
{
+ uint32_t start;
+ uint32_t end;
void *image_buffer;
int o;
@@ -3414,17 +3470,13 @@ static void VaapiUploadImage(int x, int y, int width, int height,
return;
}
- Debug(3, "video/vaapi: upload image\n");
-
+ start = GetMsTicks();
// map osd surface/image into memory.
if (vaMapBuffer(VaDisplay, VaOsdImage.buf, &image_buffer)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't map osd image buffer\n"));
return;
}
- // 100% transparent
- //memset(image_buffer, 0x00, VaOsdImage.data_size);
-
// FIXME: convert image from ARGB to subpicture format, if not argb
// copy argb to image
@@ -3436,6 +3488,10 @@ static void VaapiUploadImage(int x, int y, int width, int height,
if (vaUnmapBuffer(VaDisplay, VaOsdImage.buf) != VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't unmap osd image buffer\n"));
}
+ end = GetMsTicks();
+
+ Debug(3, "video/vaapi: osd upload %dx%d+%d+%d %d ms %d\n", width, height,
+ x, y, end - start, width * height * 4);
}
///
@@ -3528,10 +3584,32 @@ static void VaapiOsdInit(int width, int height)
}
// FIXME: must store format, to convert ARGB to it.
- VaapiOsdClear();
// FIXME: unlock
}
+///
+/// VA-API cleanup osd.
+///
+static void VaapiOsdExit(void)
+{
+ if (VaOsdImage.image_id != VA_INVALID_ID) {
+ if (vaDestroyImage(VaDisplay,
+ VaOsdImage.image_id) != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't destroy image!\n"));
+ }
+ VaOsdImage.image_id = VA_INVALID_ID;
+ }
+
+ if (VaOsdSubpicture != VA_INVALID_ID) {
+ // FIXME: still has 35 surfaces associated to it
+ if (vaDestroySubpicture(VaDisplay, VaOsdSubpicture)
+ != VA_STATUS_SUCCESS) {
+ Error(_("video/vaapi: can't destroy subpicture\n"));
+ }
+ VaOsdSubpicture = VA_INVALID_ID;
+ }
+}
+
#endif
//----------------------------------------------------------------------------
@@ -3629,10 +3707,6 @@ static int VdpauSkipChroma; ///< skip chroma deint. supported
static VdpOutputSurface VdpauSurfacesRb[OUTPUT_SURFACES_MAX];
static int VdpauSurfaceIndex; ///< current display surface
-static int VdpauOsdWidth; ///< width of osd surface
-static int VdpauOsdHeight; ///< height of osd surface
-static int VdpauShowOsd; ///< flag show osd
-
#ifdef USE_BITMAP
/// bitmap surfaces for osd
static VdpBitmapSurface VdpauOsdBitmapSurface[2] = {
@@ -4947,8 +5021,6 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
decoder->InputAspect = video_ctx->sample_aspect_ratio;
VdpauUpdateOutput(decoder);
- VdpauMixerSetup(decoder);
-
// FIXME: need only to create and destroy surfaces for size changes
// or when number of needed surfaces changed!
decoder->Resolution =
@@ -4956,6 +5028,8 @@ static enum PixelFormat Vdpau_get_format(VdpauDecoder * decoder,
decoder->Interlaced);
VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
+ VdpauMixerSetup(decoder);
+
Debug(3, "\t%#010x %s\n", fmt_idx[0], av_get_pix_fmt_name(fmt_idx[0]));
return *fmt_idx;
@@ -4983,12 +5057,13 @@ static void VdpauSetup(VdpauDecoder * decoder,
// decoder->Input... already setup by caller
VdpauCleanup(decoder);
- VdpauMixerSetup(decoder);
decoder->Resolution =
VideoResolutionGroup(video_ctx->width, video_ctx->height,
decoder->Interlaced);
VdpauCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
+ VdpauMixerSetup(decoder);
+
// get real surface size
status =
VdpauVideoSurfaceGetParameters(decoder->SurfacesFree[0], &chroma_type,
@@ -5323,15 +5398,30 @@ static void VdpauMixOsd(void)
blend_state.blend_equation_alpha =
VDP_OUTPUT_SURFACE_RENDER_BLEND_EQUATION_ADD;
- source_rect.x0 = 0;
- source_rect.y0 = 0;
- source_rect.x1 = VdpauOsdWidth;
- source_rect.y1 = VdpauOsdHeight;
+ // FIXME: use dirty area
+ if (OsdDirtyWidth && OsdDirtyHeight) {
+ source_rect.x0 = OsdDirtyX;
+ source_rect.y0 = OsdDirtyY;
+ source_rect.x1 = source_rect.x0 + OsdDirtyWidth;
+ source_rect.y1 = source_rect.y0 + OsdDirtyHeight;
+
+ output_rect.x0 = (OsdDirtyX * VideoWindowWidth) / OsdWidth;
+ output_rect.y0 = (OsdDirtyY * VideoWindowHeight) / OsdHeight;
+ output_rect.x1 =
+ output_rect.x0 + (OsdDirtyWidth * VideoWindowWidth) / OsdWidth;
+ output_rect.y1 =
+ output_rect.y0 + (OsdDirtyHeight * VideoWindowHeight) / OsdHeight;
+ } else {
+ source_rect.x0 = 0;
+ source_rect.y0 = 0;
+ source_rect.x1 = OsdWidth;
+ source_rect.y1 = OsdHeight;
- output_rect.x0 = 0;
- output_rect.y0 = 0;
- output_rect.x1 = VideoWindowWidth;
- output_rect.y1 = VideoWindowHeight;
+ output_rect.x0 = 0;
+ output_rect.y0 = 0;
+ output_rect.x1 = VideoWindowWidth;
+ output_rect.y1 = VideoWindowHeight;
+ }
//start = GetMsTicks();
@@ -5645,7 +5735,7 @@ static void VdpauDisplayFrame(void)
//
// add osd to surface
//
- if (VdpauShowOsd) { // showing costs performance
+ if (OsdShown) { // showing costs performance
VdpauMixOsd();
}
//
@@ -5879,6 +5969,8 @@ static void VdpauSetOutputPosition(VdpauDecoder * decoder, int x, int y,
// VDPAU OSD
//----------------------------------------------------------------------------
+static const uint8_t OsdZeros[1920 * 1080 * 4]; ///< 0 for clear osd
+
///
/// Clear subpicture image.
///
@@ -5887,7 +5979,6 @@ static void VdpauSetOutputPosition(VdpauDecoder * decoder, int x, int y,
static void VdpauOsdClear(void)
{
VdpStatus status;
- void *image;
void const *data[1];
uint32_t pitches[1];
VdpRect dst_rect;
@@ -5903,16 +5994,27 @@ static void VdpauOsdClear(void)
}
#endif
- Debug(3, "video/vdpau: clear image\n");
-
- image = calloc(4, VdpauOsdWidth * VdpauOsdHeight);
-
- dst_rect.x0 = 0;
- dst_rect.y0 = 0;
- dst_rect.x1 = dst_rect.x0 + VdpauOsdWidth;
- dst_rect.y1 = dst_rect.y0 + VdpauOsdHeight;
- data[0] = image;
- pitches[0] = VdpauOsdWidth * 4;
+ if (OsdWidth * OsdHeight > 1920 * 1080) {
+ Error(_("video/vdpau: osd too big: unsupported\n"));
+ return;
+ }
+ // have dirty area.
+ if (OsdDirtyWidth && OsdDirtyHeight) {
+ Debug(3, "video/vdpau: osd clear dirty %dx%d+%d+%d\n", OsdDirtyWidth,
+ OsdDirtyHeight, OsdDirtyX, OsdDirtyY);
+ dst_rect.x0 = OsdDirtyX;
+ dst_rect.y0 = OsdDirtyY;
+ dst_rect.x1 = dst_rect.x0 + OsdDirtyWidth;
+ dst_rect.y1 = dst_rect.y0 + OsdDirtyHeight;
+ } else {
+ Debug(3, "video/vdpau: osd clear image\n");
+ dst_rect.x0 = 0;
+ dst_rect.y0 = 0;
+ dst_rect.x1 = dst_rect.x0 + OsdWidth;
+ dst_rect.y1 = dst_rect.y0 + OsdHeight;
+ }
+ data[0] = OsdZeros;
+ pitches[0] = OsdWidth * 4;
#ifdef USE_BITMAP
status =
@@ -5931,9 +6033,6 @@ static void VdpauOsdClear(void)
VdpauGetErrorString(status));
}
#endif
-
- free(image);
- VdpauShowOsd = 0;
}
///
@@ -5954,6 +6053,8 @@ static void VdpauUploadImage(int x, int y, int width, int height,
void const *data[1];
uint32_t pitches[1];
VdpRect dst_rect;
+ uint32_t start;
+ uint32_t end;
// osd image available?
#ifdef USE_BITMAP
@@ -5966,7 +6067,7 @@ static void VdpauUploadImage(int x, int y, int width, int height,
}
#endif
- Debug(3, "video/vdpau: upload image\n");
+ start = GetMsTicks();
dst_rect.x0 = x;
dst_rect.y0 = y;
@@ -5992,7 +6093,10 @@ static void VdpauUploadImage(int x, int y, int width, int height,
VdpauGetErrorString(status));
}
#endif
- VdpauShowOsd = 1;
+ end = GetMsTicks();
+
+ Debug(3, "video/vdpau: osd upload %dx%d+%d+%d %d ms %d\n", width, height,
+ x, y, end - start, width * height * 4);
}
///
@@ -6010,16 +6114,12 @@ static void VdpauOsdInit(int width, int height)
Debug(3, "video/vdpau: vdpau not setup\n");
return;
}
-
- VdpauOsdWidth = width;
- VdpauOsdHeight = height;
-
//
// create bitmap/surface for osd
//
#ifdef USE_BITMAP
if (VdpauOsdBitmapSurface[0] == VDP_INVALID_HANDLE) {
- for (i = 0; i < 2; ++i) {
+ for (i = 0; i < 1; ++i) {
status =
VdpauBitmapSurfaceCreate(VdpauDevice, VDP_RGBA_FORMAT_B8G8R8A8,
width, height, VDP_TRUE, VdpauOsdBitmapSurface + i);
@@ -6034,7 +6134,7 @@ static void VdpauOsdInit(int width, int height)
}
#else
if (VdpauOsdOutputSurface[0] == VDP_INVALID_HANDLE) {
- for (i = 0; i < 2; ++i) {
+ for (i = 0; i < 1; ++i) {
status =
VdpauOutputSurfaceCreate(VdpauDevice, VDP_RGBA_FORMAT_B8G8R8A8,
width, height, VdpauOsdOutputSurface + i);
@@ -6048,10 +6148,7 @@ static void VdpauOsdInit(int width, int height)
}
}
#endif
-
Debug(3, "video/vdpau: osd surfaces created\n");
-
- VdpauOsdClear();
}
///
@@ -6059,7 +6156,38 @@ static void VdpauOsdInit(int width, int height)
///
static void VdpauOsdExit(void)
{
- Debug(3, "FIXME: %s\n", __FUNCTION__);
+ int i;
+
+ //
+ // destroy osd bitmap/output surfaces
+ //
+#ifdef USE_BITMAP
+ for (i = 0; i < 1; ++i) {
+ VdpStatus status;
+
+ if (VdpauOsdBitmapSurface[i] != VDP_INVALID_HANDLE) {
+ status = VdpauBitmapSurfaceDestroy(VdpauOsdBitmapSurface[i]);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't destroy bitmap surface: %s\n"),
+ VdpauGetErrorString(status));
+ }
+ VdpauOsdBitmapSurface[i] = VDP_INVALID_HANDLE;
+ }
+ }
+#else
+ for (i = 0; i < 1; ++i) {
+ VdpStatus status;
+
+ if (VdpauOsdOutputSurface[i] != VDP_INVALID_HANDLE) {
+ status = VdpauOutputSurfaceDestroy(VdpauOsdOutputSurface[i]);
+ if (status != VDP_STATUS_OK) {
+ Error(_("video/vdpau: can't destroy output surface: %s\n"),
+ VdpauGetErrorString(status));
+ }
+ VdpauOsdOutputSurface[i] = VDP_INVALID_HANDLE;
+ }
+ }
+#endif
}
#endif
@@ -6068,10 +6196,6 @@ static void VdpauOsdExit(void)
// OSD
//----------------------------------------------------------------------------
-//static int OsdShow; ///< flag show osd
-static int OsdWidth; ///< osd width
-static int OsdHeight; ///< osd height
-
///
/// Clear the OSD.
///
@@ -6080,6 +6204,10 @@ static int OsdHeight; ///< osd height
///
void VideoOsdClear(void)
{
+ if (!VideoThread) { // thread not yet running
+ return;
+ }
+
VideoThreadLock();
#ifdef USE_GLX
if (GlxEnabled) {
@@ -6100,6 +6228,11 @@ void VideoOsdClear(void)
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
VaapiOsdClear();
+ OsdDirtyX = OsdWidth;
+ OsdDirtyY = OsdHeight;
+ OsdDirtyWidth = 0;
+ OsdDirtyHeight = 0;
+ OsdShown = 0;
VideoThreadUnlock();
return;
}
@@ -6107,6 +6240,11 @@ void VideoOsdClear(void)
#ifdef USE_VDPAU
if (VideoVdpauEnabled) {
VdpauOsdClear();
+ OsdDirtyX = OsdWidth;
+ OsdDirtyY = OsdHeight;
+ OsdDirtyWidth = 0;
+ OsdDirtyHeight = 0;
+ OsdShown = 0;
VideoThreadUnlock();
return;
}
@@ -6123,10 +6261,36 @@ void VideoOsdClear(void)
/// @param height height of image
/// @param argb argb image
///
-void VideoOsdDrawARGB(int x, int y, int height, int width,
+void VideoOsdDrawARGB(int x, int y, int width, int height,
const uint8_t * argb)
{
+ if (!VideoThread) { // thread not yet running
+ return;
+ }
VideoThreadLock();
+
+ // update dirty area
+ if (x < OsdDirtyX) {
+ if (OsdDirtyWidth) {
+ OsdDirtyWidth += OsdDirtyX - x;
+ }
+ OsdDirtyX = x;
+ }
+ if (y < OsdDirtyY) {
+ if (OsdDirtyHeight) {
+ OsdDirtyHeight += OsdDirtyY - y;
+ }
+ OsdDirtyY = y;
+ }
+ if (x + width > OsdDirtyX + OsdDirtyWidth) {
+ OsdDirtyWidth = x + width - OsdDirtyX;
+ }
+ if (y + height > OsdDirtyY + OsdDirtyHeight) {
+ OsdDirtyHeight = y + height - OsdDirtyY;
+ }
+ Debug(3, "video: osd dirty %dx%d+%d+%d -> %dx%d+%d+%d\n", width, height, x,
+ y, OsdDirtyWidth, OsdDirtyHeight, OsdDirtyX, OsdDirtyY);
+
#ifdef USE_GLX
if (GlxEnabled) {
Debug(3, "video: %p <-> %p\n", glXGetCurrentContext(), GlxContext);
@@ -6137,15 +6301,17 @@ void VideoOsdDrawARGB(int x, int y, int height, int width,
#endif
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
- VaapiUploadImage(x, y, height, width, argb);
+ VaapiUploadImage(x, y, width, height, argb);
VideoThreadUnlock();
+ OsdShown = 1;
return;
}
#endif
#ifdef USE_VDPAU
if (VideoVdpauEnabled) {
- VdpauUploadImage(x, y, height, width, argb);
+ VdpauUploadImage(x, y, width, height, argb);
VideoThreadUnlock();
+ OsdShown = 1;
return;
}
#endif
@@ -6158,6 +6324,19 @@ void VideoOsdDrawARGB(int x, int y, int height, int width,
}
///
+/// Get OSD size.
+///
+void VideoGetOsdSize(int *width, int *height)
+{
+ *width = 1920;
+ *height = 1080; // unknown default
+ if (OsdWidth && OsdHeight) {
+ *width = OsdWidth;
+ *height = OsdHeight;
+ }
+}
+
+///
/// Setup osd.
///
/// FIXME: looking for BGRA, but this fourcc isn't supported by the
@@ -6165,11 +6344,8 @@ void VideoOsdDrawARGB(int x, int y, int height, int width,
///
void VideoOsdInit(void)
{
- OsdWidth = 1920 / 1;
- OsdHeight = 1080 / 1; // worst-case
-
- //OsdWidth = 768;
- //OsdHeight = VideoWindowHeight; // FIXME: must be configured
+ OsdWidth = VideoWindowWidth; // FIXME: must be configured
+ OsdHeight = VideoWindowHeight;
#ifdef USE_GLX
// FIXME: make an extra function for this
@@ -6205,12 +6381,14 @@ void VideoOsdInit(void)
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
VaapiOsdInit(OsdWidth, OsdHeight);
+ VideoOsdClear();
return;
}
#endif
#ifdef USE_VDPAU
if (VideoVdpauEnabled) {
VdpauOsdInit(OsdWidth, OsdHeight);
+ VideoOsdClear();
return;
}
#endif
@@ -6223,7 +6401,7 @@ void VideoOsdExit(void)
{
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
- // FIXME: VaapiOsdExit();
+ VaapiOsdExit();
return;
}
#endif
@@ -7070,27 +7248,45 @@ void VideoSetVideoMode( __attribute__ ((unused))
int y, int width, int height)
{
Debug(3, "video: %s %dx%d%+d%+d\n", __FUNCTION__, width, height, x, y);
+
if ((unsigned)width == VideoWindowWidth
&& (unsigned)height == VideoWindowHeight) {
return; // same size nothing todo
}
+
+ if (!VideoThread) { // thread not yet running
+ return;
+ }
+ //VideoThreadLock(); // FIXME: vaapi can crash
+
VideoWindowWidth = width;
VideoWindowHeight = height;
#ifdef USE_VAAPI
if (VideoVaapiEnabled && VaapiDecoders[0]) {
- // FIXME: must update osd surfaces?
+ VaapiDeassociate(VaapiDecoders[0]);
+ VideoOsdExit();
+ VideoOsdInit();
+ if (VaapiDecoders[0]->InputWidth && VaapiDecoders[0]->InputHeight) {
+ VaapiAssociate(VaapiDecoders[0], VaapiDecoders[0]->InputWidth,
+ VaapiDecoders[0]->InputHeight);
+ }
VaapiUpdateOutput(VaapiDecoders[0]);
+ //VideoThreadUnlock();
return;
}
#endif
#ifdef USE_VDPAU
if (VideoVdpauEnabled && VdpauDecoders[0]) {
VdpauExitOutputQueue();
+ VideoOsdExit();
+ VideoOsdInit();
VdpauInitOutputQueue();
VdpauUpdateOutput(VdpauDecoders[0]);
+ //VideoThreadUnlock();
return;
}
#endif
+ //VideoThreadUnlock();
}
///