Fix bug: wrong and crash, if vdr draws pixmaps outside OSD.

This commit is contained in:
Johns 2015-06-30 10:12:09 +02:00
parent 396d5fac05
commit ec58e45607
6 changed files with 201 additions and 74 deletions

View File

@ -1,6 +1,7 @@
User johns User johns
Date: Date:
Fix bug: wrong and crash, if vdr draws pixmaps outside OSD.
Fix bug: wrong version number check for av_frame_alloc(), ... Fix bug: wrong version number check for av_frame_alloc(), ...
Workaround for ffmpeg 2.6 artifacts. Workaround for ffmpeg 2.6 artifacts.
Fix bug: brightness and .. are calculated wrong. Fix bug: brightness and .. are calculated wrong.

View File

@ -2866,17 +2866,21 @@ void OsdClose(void)
/** /**
** Draw an OSD pixmap. ** Draw an OSD pixmap.
** **
** @param xi x-coordinate in argb image
** @param yi y-coordinate in argb image
** @paran height height in pixel in argb image
** @paran width width in pixel in argb image
** @param pitch pitch of argb image
** @param argb 32bit ARGB image data
** @param x x-coordinate on screen of argb image ** @param x x-coordinate on screen of argb image
** @param y y-coordinate on screen of argb image ** @param y y-coordinate on screen of argb image
** @paran height height in pixel of argb image
** @paran width width in pixel of argb image
** @param argb height * width 32bit ARGB image data
*/ */
void OsdDrawARGB(int x, int y, int height, int width, const uint8_t * argb) void OsdDrawARGB(int xi, int yi, int height, int width, int pitch,
const uint8_t * argb, int x, int y)
{ {
// wakeup display for showing remote learning dialog // wakeup display for showing remote learning dialog
VideoDisplayWakeup(); VideoDisplayWakeup();
VideoOsdDrawARGB(x, y, height, width, argb); VideoOsdDrawARGB(xi, yi, height, width, pitch, argb, x, y);
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddev.h @brief software HD device plugin header file. /// @file softhddev.h @brief software HD device plugin header file.
/// ///
/// Copyright (c) 2011 - 2014 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -34,7 +34,8 @@ extern "C"
/// C plugin close osd /// C plugin close osd
extern void OsdClose(void); extern void OsdClose(void);
/// C plugin draw osd pixmap /// C plugin draw osd pixmap
extern void OsdDrawARGB(int, int, int, int, const uint8_t *); extern void OsdDrawARGB(int, int, int, int, int, const uint8_t *, int,
int);
/// C plugin play audio packet /// C plugin play audio packet
extern int PlayAudio(const uint8_t *, int, uint8_t); extern int PlayAudio(const uint8_t *, int, uint8_t);

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddevice.cpp @brief A software HD device plugin for VDR. /// @file softhddevice.cpp @brief A software HD device plugin for VDR.
/// ///
/// Copyright (c) 2011 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -431,6 +431,8 @@ void cSoftOsd::Flush(void)
// draw all bitmaps // draw all bitmaps
for (i = 0; (bitmap = GetBitmap(i)); ++i) { for (i = 0; (bitmap = GetBitmap(i)); ++i) {
uint8_t *argb; uint8_t *argb;
int xs;
int ys;
int x; int x;
int y; int y;
int w; int w;
@ -449,22 +451,52 @@ void cSoftOsd::Flush(void)
} else if (!bitmap->Dirty(x1, y1, x2, y2)) { } else if (!bitmap->Dirty(x1, y1, x2, y2)) {
continue; // nothing dirty continue continue; // nothing dirty continue
} }
// convert and upload only dirty areas // convert and upload only visible dirty areas
xs = bitmap->X0() + Left();
ys = bitmap->Y0() + Top();
// FIXME: negtative position bitmaps
w = x2 - x1 + 1; w = x2 - x1 + 1;
h = y2 - y1 + 1; h = y2 - y1 + 1;
// clip to screen
if (1) { // just for the case it makes trouble if (1) { // just for the case it makes trouble
int width; int width;
int height; int height;
double video_aspect; double video_aspect;
::GetOsdSize(&width, &height, &video_aspect); if (xs < 0) {
if (w > width) { if (xs + x1 < 0) {
w = width; x1 -= xs + x1;
x2 = x1 + width - 1; w += xs + x1;
if (w <= 0) {
continue;
}
}
xs = 0;
} }
if (h > height) { if (ys < 0) {
h = height; if (ys + y1 < 0) {
y2 = y1 + height - 1; y1 -= ys + y1;
h += ys + y1;
if (h <= 0) {
continue;
}
}
ys = 0;
}
::GetOsdSize(&width, &height, &video_aspect);
if (w > width - xs - x1) {
w = width - xs - x1;
if (w <= 0) {
continue;
}
x2 = x1 + w - 1;
}
if (h > height - ys - y1) {
h = height - ys - y1;
if (h <= 0) {
continue;
}
y2 = y1 + h - 1;
} }
} }
#ifdef DEBUG #ifdef DEBUG
@ -482,10 +514,10 @@ void cSoftOsd::Flush(void)
} }
#ifdef OSD_DEBUG #ifdef OSD_DEBUG
dsyslog("[softhddev]%s: draw %dx%d%+d%+d bm\n", __FUNCTION__, w, h, dsyslog("[softhddev]%s: draw %dx%d%+d%+d bm\n", __FUNCTION__, w, h,
Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1); xs + x1, ys + y1);
#endif #endif
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1, OsdDrawARGB(0, 0, w, h, w * sizeof(uint32_t), argb, xs + x1,
w, h, argb); ys + y1);
bitmap->Clean(); bitmap->Clean();
// FIXME: reuse argb // FIXME: reuse argb
@ -497,21 +529,76 @@ void cSoftOsd::Flush(void)
LOCK_PIXMAPS; LOCK_PIXMAPS;
while ((pm = (dynamic_cast < cPixmapMemory * >(RenderPixmaps())))) { while ((pm = (dynamic_cast < cPixmapMemory * >(RenderPixmaps())))) {
int xp;
int yp;
int stride;
int x; int x;
int y; int y;
int w; int w;
int h; int h;
x = Left() + pm->ViewPort().X(); x = pm->ViewPort().X();
y = Top() + pm->ViewPort().Y(); y = pm->ViewPort().Y();
w = pm->ViewPort().Width(); w = pm->ViewPort().Width();
h = pm->ViewPort().Height(); h = pm->ViewPort().Height();
stride = w * sizeof(tColor);
// clip to osd
xp = 0;
if (x < 0) {
xp = -x;
w -= xp;
x = 0;
}
yp = 0;
if (y < 0) {
yp = -y;
h -= yp;
y = 0;
}
if (w > Width() - x) {
w = Width() - x;
}
if (h > Height() - y) {
h = Height() - y;
}
x += Left();
y += Top();
// clip to screen
if (1) { // just for the case it makes trouble
// and it can happen!
int width;
int height;
double video_aspect;
if (x < 0) {
w += x;
xp += -x;
x = 0;
}
if (y < 0) {
h += y;
yp += -y;
y = 0;
}
::GetOsdSize(&width, &height, &video_aspect);
if (w > width - x) {
w = width - x;
}
if (h > height - y) {
h = height - y;
}
}
#ifdef OSD_DEBUG #ifdef OSD_DEBUG
dsyslog("[softhddev]%s: draw %dx%d%+d%+d %p\n", __FUNCTION__, w, h, x, dsyslog("[softhddev]%s: draw %dx%d%+d%+d*%d -> %+d%+d %p\n",
y, pm->Data()); __FUNCTION__, w, h, xp, yp, stride, x, y, pm->Data());
#endif #endif
OsdDrawARGB(x, y, w, h, pm->Data()); OsdDrawARGB(xp, yp, w, h, stride, pm->Data(), x, y);
#if APIVERSNUM >= 20110 #if APIVERSNUM >= 20110
DestroyPixmap(pm); DestroyPixmap(pm);

129
video.c
View File

@ -1,7 +1,7 @@
/// ///
/// @file video.c @brief Video module /// @file video.c @brief Video module
/// ///
/// Copyright (c) 2009 - 2014 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -280,7 +280,8 @@ typedef struct _video_module_
void (*const OsdClear) (void); ///< clear OSD void (*const OsdClear) (void); ///< clear OSD
/// draw OSD ARGB area /// draw OSD ARGB area
void (*const OsdDrawARGB) (int, int, int, int, const uint8_t *); void (*const OsdDrawARGB) (int, int, int, int, int, const uint8_t *, int,
int);
void (*const OsdInit) (int, int); ///< initialize OSD void (*const OsdInit) (int, int); ///< initialize OSD
void (*const OsdExit) (void); ///< cleanup OSD void (*const OsdExit) (void); ///< cleanup OSD
@ -887,17 +888,22 @@ static void GlxOsdExit(void)
/// ///
/// Upload ARGB image to texture. /// Upload ARGB image to texture.
/// ///
/// @param x x coordinate of image in osd texture /// @param xi x-coordinate in argb image
/// @param y y coordinate of image in osd texture /// @param yi y-coordinate in argb image
/// @param width width of image /// @paran height height in pixel in argb image
/// @param height height of image /// @paran width width in pixel in argb image
/// @param argb argb image /// @param pitch pitch of argb image
/// @param argb 32bit ARGB image data
/// @param x x-coordinate on screen of argb image
/// @param y y-coordinate on screen of argb image
/// ///
/// @note looked by caller /// @note looked by caller
/// ///
static void GlxOsdDrawARGB(int x, int y, int width, int height, static void GlxOsdDrawARGB(int xi, int yi, int width, int height, int pitch,
const uint8_t * argb) const uint8_t * argb, int x, int y)
{ {
uint8_t *tmp;
#ifdef DEBUG #ifdef DEBUG
uint32_t start; uint32_t start;
uint32_t end; uint32_t end;
@ -918,9 +924,21 @@ static void GlxOsdDrawARGB(int x, int y, int width, int height,
Error(_("video/glx: can't make glx context current\n")); Error(_("video/glx: can't make glx context current\n"));
return; return;
} }
GlxUploadOsdTexture(x, y, width, height, argb); // FIXME: faster way
glXMakeCurrent(XlibDisplay, None, NULL); tmp = malloc(width * height * 4);
if (tmp) {
int i;
for (i = 0; i < height; ++i) {
memcpy(tmp + i * width * 4, argb + xi * 4 + (i + yi) * pitch,
width * 4);
}
GlxUploadOsdTexture(x, y, width, height, tmp);
glXMakeCurrent(XlibDisplay, None, NULL);
free(tmp);
}
#ifdef DEBUG #ifdef DEBUG
end = GetMsTicks(); end = GetMsTicks();
@ -1331,11 +1349,11 @@ static int AutoCropTolerance; ///< auto-crop tolerance
/// ///
/// @param data Y plane pixel data /// @param data Y plane pixel data
/// @param length number of pixel to check /// @param length number of pixel to check
/// @param stride offset of pixels /// @param pitch offset of pixels
/// ///
/// @note 8 pixel are checked at once, all values must be 8 aligned /// @note 8 pixel are checked at once, all values must be 8 aligned
/// ///
static int AutoCropIsBlackLineY(const uint8_t * data, int length, int stride) static int AutoCropIsBlackLineY(const uint8_t * data, int length, int pitch)
{ {
int n; int n;
int o; int o;
@ -1343,13 +1361,13 @@ static int AutoCropIsBlackLineY(const uint8_t * data, int length, int stride)
const uint64_t *p; const uint64_t *p;
#ifdef DEBUG #ifdef DEBUG
if ((size_t) data & 0x7 || stride & 0x7) { if ((size_t) data & 0x7 || pitch & 0x7) {
abort(); abort();
} }
#endif #endif
p = (const uint64_t *)data; p = (const uint64_t *)data;
n = length; // FIXME: can remove n n = length; // FIXME: can remove n
o = stride / 8; o = pitch / 8;
r = 0UL; r = 0UL;
while (--n >= 0) { while (--n >= 0) {
@ -5438,16 +5456,19 @@ static void VaapiOsdClear(void)
/// ///
/// Upload ARGB to subpicture image. /// Upload ARGB to subpicture image.
/// ///
/// @param x x position of image in osd /// @param xi x-coordinate in argb image
/// @param y y position of image in osd /// @param yi y-coordinate in argb image
/// @param width width of image /// @paran height height in pixel in argb image
/// @param height height of image /// @paran width width in pixel in argb image
/// @param argb argb image /// @param pitch pitch of argb image
/// @param argb 32bit ARGB image data
/// @param x x-coordinate on screen of argb image
/// @param y y-coordinate on screen of argb image
/// ///
/// @note looked by caller /// @note looked by caller
/// ///
static void VaapiOsdDrawARGB(int x, int y, int width, int height, static void VaapiOsdDrawARGB(int xi, int yi, int width, int height, int pitch,
const uint8_t * argb) const uint8_t * argb, int x, int y)
{ {
#ifdef DEBUG #ifdef DEBUG
uint32_t start; uint32_t start;
@ -5474,7 +5495,7 @@ static void VaapiOsdDrawARGB(int x, int y, int width, int height,
// copy argb to image // copy argb to image
for (o = 0; o < height; ++o) { for (o = 0; o < height; ++o) {
memcpy(image_buffer + (x + (y + o) * VaOsdImage.width) * 4, memcpy(image_buffer + (x + (y + o) * VaOsdImage.width) * 4,
argb + o * width * 4, width * 4); argb + xi * 4 + (o + yi) * pitch, width * 4);
} }
if (vaUnmapBuffer(VaDisplay, VaOsdImage.buf) != VA_STATUS_SUCCESS) { if (vaUnmapBuffer(VaDisplay, VaOsdImage.buf) != VA_STATUS_SUCCESS) {
@ -9240,16 +9261,19 @@ static void VdpauOsdClear(void)
/// ///
/// Upload ARGB to subpicture image. /// Upload ARGB to subpicture image.
/// ///
/// @param x x position of image in osd /// @param xi x-coordinate in argb image
/// @param y y position of image in osd /// @param yi y-coordinate in argb image
/// @param width width of image /// @paran height height in pixel in argb image
/// @param height height of image /// @paran width width in pixel in argb image
/// @param argb argb image /// @param pitch pitch of argb image
/// @param argb 32bit ARGB image data
/// @param x x-coordinate on screen of argb image
/// @param y y-coordinate on screen of argb image
/// ///
/// @note looked by caller /// @note looked by caller
/// ///
static void VdpauOsdDrawARGB(int x, int y, int width, int height, static void VdpauOsdDrawARGB(int xi, int yi, int width, int height, int pitch,
const uint8_t * argb) const uint8_t * argb, int x, int y)
{ {
VdpStatus status; VdpStatus status;
void const *data[1]; void const *data[1];
@ -9283,8 +9307,8 @@ static void VdpauOsdDrawARGB(int x, int y, int width, int height,
dst_rect.y0 = y; dst_rect.y0 = y;
dst_rect.x1 = dst_rect.x0 + width; dst_rect.x1 = dst_rect.x0 + width;
dst_rect.y1 = dst_rect.y0 + height; dst_rect.y1 = dst_rect.y0 + height;
data[0] = argb; data[0] = argb + xi * 4 + yi * pitch;
pitches[0] = width * 4; pitches[0] = pitch;
#ifdef USE_BITMAP #ifdef USE_BITMAP
status = status =
@ -9499,20 +9523,26 @@ static void NoopOsdInit( __attribute__ ((unused))
/// ///
/// Draw OSD ARGB image. /// Draw OSD ARGB image.
/// ///
/// @param x x position of image in osd /// @param xi x-coordinate in argb image
/// @param y y position of image in osd /// @param yi y-coordinate in argb image
/// @param width width of image /// @paran height height in pixel in argb image
/// @param height height of image /// @paran width width in pixel in argb image
/// @param argb argb image /// @param pitch pitch of argb image
/// @param argb 32bit ARGB image data
/// @param x x-coordinate on screen of argb image
/// @param y y-coordinate on screen of argb image
/// ///
/// @note looked by caller /// @note looked by caller
/// ///
static void NoopOsdDrawARGB( __attribute__ ((unused)) static void NoopOsdDrawARGB( __attribute__ ((unused))
int x, __attribute__ ((unused)) int xi, __attribute__ ((unused))
int y, __attribute__ ((unused)) int yi, __attribute__ ((unused))
int width, __attribute__ ((unused)) int width, __attribute__ ((unused))
int height, __attribute__ ((unused)) int height, __attribute__ ((unused))
const uint8_t * argb) int pitch, __attribute__ ((unused))
const uint8_t * argb, __attribute__ ((unused))
int x, __attribute__ ((unused))
int y)
{ {
} }
@ -9631,14 +9661,17 @@ void VideoOsdClear(void)
/// ///
/// Draw an OSD ARGB image. /// Draw an OSD ARGB image.
/// ///
/// @param x x position of image in osd /// @param xi x-coordinate in argb image
/// @param y y position of image in osd /// @param yi y-coordinate in argb image
/// @param width width of image /// @paran height height in pixel in argb image
/// @param height height of image /// @paran width width in pixel in argb image
/// @param argb argb image /// @param pitch pitch of argb image
/// @param argb 32bit ARGB image data
/// @param x x-coordinate on screen of argb image
/// @param y y-coordinate on screen of argb image
/// ///
void VideoOsdDrawARGB(int x, int y, int width, int height, void VideoOsdDrawARGB(int xi, int yi, int width, int height, int pitch,
const uint8_t * argb) const uint8_t * argb, int x, int y)
{ {
VideoThreadLock(); VideoThreadLock();
// update dirty area // update dirty area
@ -9663,7 +9696,7 @@ void VideoOsdDrawARGB(int x, int y, int width, int height,
Debug(4, "video: osd dirty %dx%d%+d%+d -> %dx%d%+d%+d\n", width, height, x, Debug(4, "video: osd dirty %dx%d%+d%+d -> %dx%d%+d%+d\n", width, height, x,
y, OsdDirtyWidth, OsdDirtyHeight, OsdDirtyX, OsdDirtyY); y, OsdDirtyWidth, OsdDirtyHeight, OsdDirtyX, OsdDirtyY);
VideoUsedModule->OsdDrawARGB(x, y, width, height, argb); VideoUsedModule->OsdDrawARGB(xi, yi, width, height, pitch, argb, x, y);
OsdShown = 1; OsdShown = 1;
VideoThreadUnlock(); VideoThreadUnlock();

View File

@ -1,7 +1,7 @@
/// ///
/// @file video.h @brief Video module header file /// @file video.h @brief Video module header file
/// ///
/// Copyright (c) 2009 - 2013 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2015 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -168,7 +168,8 @@ extern void VideoSetAutoCrop(int, int, int);
extern void VideoOsdClear(void); extern void VideoOsdClear(void);
/// Draw an OSD ARGB image. /// Draw an OSD ARGB image.
extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *); extern void VideoOsdDrawARGB(int, int, int, int, int, const uint8_t *, int,
int);
/// Get OSD size. /// Get OSD size.
extern void VideoGetOsdSize(int *, int *); extern void VideoGetOsdSize(int *, int *);