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, ...
This commit is contained in:
Johns 2012-01-18 15:15:37 +01:00
parent 19d4eeed82
commit c6e66e0787
6 changed files with 399 additions and 168 deletions

View File

@ -1,6 +1,11 @@
User johns
Date:
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, ...
Fix software deinterlace with VA-API.
Fix bug: transposed digits 567 should be 576.
Audio module cleanup:

15
Todo
View File

@ -19,23 +19,20 @@ GNU Affero General Public License for more details.
$Id: $
missing:
software deinterlace
software deinterlace (yadif, ...)
software decoder with software deinterlace
auto crop
zoom/fit-zoom 4:3 (SetVideoDisplayFormat, SetVideoFormat?)
ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)?
suspend output / energie saver: stop audio, stop video, configurable
Option deinterlace off / deinterlace force!
Make output drivers better moduluar.
Make output drivers better modular.
video:
subtitle not cleared
subtitle could be asyncron
vdpau:
1080i with temporal spatial and level 1 scaling too slow with my GT 520
1080i with temporal spatial too slow with my GT 520 on some channels
SkipChromaDeinterlace improves performance
Improve OSD handling, show only what is used. Big OSD costs performance
VdpPreemptionCallback handling
hard channel switch
suspendoutput didn't show logo or black picture.
@ -43,15 +40,15 @@ vdpau:
libva:
hard channel switch
yaepghd (VaapiSetOutputPosition) support
can associate ony displayed part of osd
libva-intel-driver:
intel still has hangups most with 1080i
1080i does no v-sync (workaround written)
osd has sometimes wrong size (workaround written)
OSD has sometimes wrong size (workaround written)
libva-vdpau-driver:
G210 osd update too slow (needs hardware problem workaround)
OSD update is too slow
G210/GT520 OSD update too slow (needs hardware problem workaround)
hangup on exit (VaapiDelDecoder -> VaapiCleanup
-> vaDestroyContext -> pthread_rwlock_wrlock)

View File

@ -913,22 +913,19 @@ int Flush(int timeout)
void GetOsdSize(int *width, int *height, double *aspect)
{
#ifdef DEBUG
static char done;
static int done_width;
static int done_height;
#endif
// FIXME: should be configured!
*width = 1920;
*height = 1080;
//*width = 768;
//*height = 576;
VideoGetOsdSize(width, height);
*aspect = 16.0 / 9.0 / (double)*width * (double)*height;
#ifdef DEBUG
if (!done) {
if (done_width != *width || done_height != *height) {
Debug(3, "[softhddev]%s: %dx%d %g\n", __FUNCTION__, *width, *height,
*aspect);
done = 1;
done_width = *width;
done_height = *height;
}
#endif
}

View File

@ -53,6 +53,7 @@ static class cSoftHdDevice *MyDevice;
#define RESOLUTIONS 4 ///< number of resolutions
/// resolutions names
static const char *const Resolution[RESOLUTIONS] = {
"576i", "720p", "1080i_fake", "1080i"
};
@ -158,8 +159,15 @@ cSoftOsd::~cSoftOsd(void)
SetActive(false);
#ifdef USE_YAEPG
if (vidWin.bpp) {
VideoSetOutputPosition(0, 0, 1920, 1080);
// support yaepghd, video window
if (vidWin.bpp) { // restore fullsized video
int width;
int height;
double video_aspect;
::GetOsdSize(&width, &height, &video_aspect);
// works osd relative
VideoSetOutputPosition(0, 0, width, height);
}
#endif
OsdClose();
@ -175,8 +183,8 @@ void cSoftOsd::Flush(void)
if (!Active()) {
return;
}
// support yaepghd, video window
#ifdef USE_YAEPG
// support yaepghd, video window
if (vidWin.bpp) {
dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, vidWin.Width(),
vidWin.Height(), vidWin.x1, vidWin.y2);
@ -213,6 +221,7 @@ void cSoftOsd::Flush(void)
if (!bitmap->Dirty(x1, y1, x2, y2)) {
continue; // nothing dirty continue
}
#if 0
// FIXME: need only to convert and upload dirty areas
// DrawBitmap(bitmap);
@ -225,7 +234,6 @@ void cSoftOsd::Flush(void)
((uint32_t *) argb)[x + y * w] = bitmap->GetColor(x, y);
}
}
// check if subtitles
if (this->Level == OSD_LEVEL_SUBTITLES) {
int video_width;
@ -238,12 +246,32 @@ void cSoftOsd::Flush(void)
video_width = 1920;
video_height = 1080;
OsdDrawARGB((1920 - video_width) / 2 + Left() + bitmap->X0(),
1080 - video_height + Top() + bitmap->Y0(),
bitmap->Width(), bitmap->Height(), argb);
1080 - video_height + Top() + bitmap->Y0(), w, h, argb);
} else {
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(),
bitmap->Width(), bitmap->Height(), argb);
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(), w, h,
argb);
}
#else
// convert and upload only dirty areas
w = x2 - x1 + 1;
h = y2 - y1 + 1;
#ifdef DEBUG
if (w > bitmap->Width() || h > bitmap->Height()) {
esyslog(tr("softhdev: dirty area too big\n"));
abort();
}
#endif
argb = (uint8_t *) malloc(w * h * sizeof(uint32_t));
for (y = y1; y <= y2; ++y) {
for (x = x1; x <= x2; ++x) {
((uint32_t *) argb)[x - x1 + (y - y1) * w] =
bitmap->GetColor(x, y);
}
}
// check if subtitles
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1,
w, h, argb);
#endif
bitmap->Clean();
free(argb);
@ -475,12 +503,7 @@ class cSoftHdDevice:public cDevice
virtual bool Poll(cPoller &, int = 0);
virtual bool Flush(int = 0);
virtual int64_t GetSTC(void);
virtual void GetVideoSize(int &width, int &height, double &aspect)
{
width = 1920;
height = 1080;
aspect = (double)width / height;
}
virtual void GetVideoSize(int &, int &, double &);
virtual void GetOsdSize(int &, int &, double &);
virtual int PlayVideo(const uchar *, int);
@ -536,18 +559,17 @@ void cSoftHdDevice::MakePrimaryDevice(bool on)
}
}
int cSoftHdDevice::ProvidesCa(
__attribute__ ((unused)) const cChannel *
channel) const
{
//dsyslog("[softhddev]%s: %p\n", __FUNCTION__, channel);
int cSoftHdDevice::ProvidesCa(
__attribute__ ((unused)) const cChannel * channel) const
{
//dsyslog("[softhddev]%s: %p\n", __FUNCTION__, channel);
return 0;
}
return 0;
}
#if 0
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
{
dsyslog("[softhddev]%s:\n", __FUNCTION__);
@ -697,7 +719,18 @@ bool cSoftHdDevice::Flush(int timeout_ms)
// ----------------------------------------------------------------------------
/**
** Returns the With, Height and PixelAspect ratio the OSD.
** Returns the width, height and video_aspect ratio of the currently
** displayed video material.
**
** @note the size is used to scale the subtitle.
*/
void cSoftHdDevice::GetVideoSize(int &width, int &height, double &video_aspect)
{
::GetOsdSize(&width, &height, &video_aspect);
}
/**
** Returns the width, height and pixel_aspect ratio the OSD.
**
** FIXME: Called every second, for nothing (no OSD displayed)?
*/

450
video.c
View File

@ -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;
@ -1009,6 +1018,92 @@ static void VaapiDestroyDeinterlaceImages(VaapiDecoder *);
// Surfaces -------------------------------------------------------------
///
/// Associate OSD with surface.
///
/// @param decoder VA-API decoder
/// @param width surface source/video width
/// @param height surface source/video height
///
static void VaapiAssociate(VaapiDecoder * decoder, int width, int height)
{
int x;
int y;
int w;
int h;
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 (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 (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"));
}
}
}
///
/// Deassociate OSD with surface.
///
/// @param decoder VA-API decoder
///
static void VaapiDeassociate(VaapiDecoder * decoder)
{
if (VaOsdSubpicture != VA_INVALID_ID) {
if (decoder->SurfaceFreeN
&& vaDeassociateSubpicture(VaDisplay, VaOsdSubpicture,
decoder->SurfacesFree, decoder->SurfaceFreeN)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't deassociate %d surfaces\n"),
decoder->SurfaceFreeN);
}
if (decoder->SurfaceUsedN
&& vaDeassociateSubpicture(VaDisplay, VaOsdSubpicture,
decoder->SurfacesUsed, decoder->SurfaceUsedN)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't deassociate %d surfaces\n"),
decoder->SurfaceUsedN);
}
}
}
///
/// Create surfaces for VA-API decoder.
///
@ -1039,27 +1134,7 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
//
// update OSD associate
//
if (VaOsdSubpicture == VA_INVALID_ID) {
Warning(_("video/vaapi: no osd subpicture yet\n"));
return;
}
// 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)
!= 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)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't associate subpicture\n"));
}
}
VaapiAssociate(decoder, width, height);
}
///
@ -1074,23 +1149,7 @@ static void VaapiDestroySurfaces(VaapiDecoder * decoder)
//
// update OSD associate
//
if (VaOsdSubpicture != VA_INVALID_ID) {
if (decoder->SurfaceFreeN
&& vaDeassociateSubpicture(VaDisplay, VaOsdSubpicture,
decoder->SurfacesFree, decoder->SurfaceFreeN)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't deassociate %d surfaces\n"),
decoder->SurfaceFreeN);
}
if (decoder->SurfaceUsedN
&& vaDeassociateSubpicture(VaDisplay, VaOsdSubpicture,
decoder->SurfacesUsed, decoder->SurfaceUsedN)
!= VA_STATUS_SUCCESS) {
Error(_("video/vaapi: can't deassociate %d surfaces\n"),
decoder->SurfaceUsedN);
}
}
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 = 0;
output_rect.y0 = 0;
output_rect.x1 = VideoWindowWidth;
output_rect.y1 = VideoWindowHeight;
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;
}
//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
@ -6157,6 +6323,19 @@ void VideoOsdDrawARGB(int x, int y, int height, int width,
VideoThreadUnlock();
}
///
/// Get OSD size.
///
void VideoGetOsdSize(int *width, int *height)
{
*width = 1920;
*height = 1080; // unknown default
if (OsdWidth && OsdHeight) {
*width = OsdWidth;
*height = OsdHeight;
}
}
///
/// Setup osd.
///
@ -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();
}
///

View File

@ -103,6 +103,9 @@ extern void VideoOsdClear(void);
/// Draw an OSD ARGB image.
extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
/// Get OSD size.
extern void VideoGetOsdSize(int *, int *);
extern int64_t VideoGetClock(void); ///< Get video clock.
extern void VideoOsdInit(void); ///< Setup osd.