mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
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:
parent
19d4eeed82
commit
c6e66e0787
@ -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
15
Todo
@ -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)
|
||||
|
||||
|
15
softhddev.c
15
softhddev.c
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
int cSoftHdDevice::ProvidesCa(
|
||||
__attribute__ ((unused)) const cChannel * channel) const
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %p\n", __FUNCTION__, channel);
|
||||
|
||||
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)?
|
||||
*/
|
||||
|
430
video.c
430
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;
|
||||
@ -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;
|
||||
}
|
||||
// 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;
|
||||
|
||||
// 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 = VdpauOsdWidth;
|
||||
source_rect.y1 = VdpauOsdHeight;
|
||||
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);
|
||||
|
||||
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 + VdpauOsdWidth;
|
||||
dst_rect.y1 = dst_rect.y0 + VdpauOsdHeight;
|
||||
data[0] = image;
|
||||
pitches[0] = VdpauOsdWidth * 4;
|
||||
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();
|
||||
}
|
||||
|
||||
///
|
||||
|
3
video.h
3
video.h
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user