1
0
mirror of https://github.com/jojo61/vdr-plugin-softhdcuvid.git synced 2023-10-10 13:37:41 +02:00

Fix DETA/ATTA with DRM (hopefully)

This commit is contained in:
jojo61 2020-01-07 22:22:07 +01:00
parent 2f0b1d0df9
commit 70b67f4466
3 changed files with 196 additions and 138 deletions

47
drm.c
View File

@ -23,6 +23,7 @@ struct _Drm_Render_
uint32_t connector_id, crtc_id, video_plane;
uint32_t hdr_metadata;
uint32_t mmWidth,mmHeight; // Size in mm
uint32_t hdr_blob_id;
};
typedef struct _Drm_Render_ VideoRender;
@ -207,10 +208,10 @@ static int FindDevice(VideoRender * render)
fprintf(stderr, "FindDevice: cannot open /dev/dri/card0: %m\n");
return -errno;
}
drmSetMaster(render->fd_drm);
version = drmGetVersion(render->fd_drm);
fprintf(stderr, "FindDevice: open /dev/dri/card0: %i %s\n", version->name_len, version->name);
fprintf(stderr, "FindDevice: open /dev/dri/card0: %s\n", version->name);
// check capability
if (drmGetCap(render->fd_drm, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || has_dumb == 0)
@ -375,8 +376,6 @@ static int FindDevice(VideoRender * render)
return 0;
}
///
/// Initialize video output module.
///
@ -384,6 +383,7 @@ void VideoInitDrm()
{
int i;
if (!(render = calloc(1, sizeof(*render)))) {
Fatal(_("video/DRM: out of memory\n"));
return;
@ -398,7 +398,7 @@ void VideoInitDrm()
PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL;
get_platform_display =
(void *) eglGetProcAddress("eglGetPlatformDisplayEXT");
(void *) eglGetProcAddress("eglGetPlatformDisplay");
assert(get_platform_display != NULL);
eglDisplay = get_platform_display(EGL_PLATFORM_GBM_KHR, gbm.dev, NULL);
@ -418,7 +418,7 @@ void VideoInitDrm()
fprintf(stderr, "cannot allocate atomic request (%d): %m\n", errno);
return;
}
printf("set CRTC %d of Connector %d aktiv\n",render->crtc_id,render->connector_id);
SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id,
DRM_MODE_OBJECT_CRTC, "MODE_ID", modeID);
SetPropertyRequest(ModeReq, render->fd_drm, render->connector_id,
@ -430,7 +430,7 @@ void VideoInitDrm()
fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno);
if (drmModeDestroyPropertyBlob(render->fd_drm, modeID) != 0)
fprintf(stderr, "cannot destroy prperty blob (%d): %m\n", errno);
fprintf(stderr, "cannot destroy property blob (%d): %m\n", errno);
drmModeAtomicFree(ModeReq);
@ -438,6 +438,7 @@ void VideoInitDrm()
void get_drm_aspect(int *num,int *den)
{
Debug(3,"mmHeight %d mmWidth %d VideoHeight %d VideoWidth %d\n",render->mmHeight,render->mmWidth,VideoWindowHeight,VideoWindowWidth);
*num = VideoWindowWidth * render->mmHeight;
*den = VideoWindowHeight * render->mmWidth;
}
@ -456,6 +457,7 @@ void InitBo(int bpp) {
assert(gbm.surface != NULL);
eglSurface = eglCreateWindowSurface (eglDisplay, eglConfig, gbm.surface, NULL);
assert(eglSurface != NULL);
}
static struct gbm_bo *previous_bo = NULL;
@ -526,6 +528,7 @@ static void drm_swap_buffers () {
}
previous_bo = bo;
previous_fb = fb;
}
static void drm_clean_up () {
@ -533,20 +536,36 @@ static void drm_clean_up () {
if (!render)
return;
Debug(3,"drm clean up\n");
if (previous_bo) {
drmModeRmFB (render->fd_drm, previous_fb);
gbm_surface_release_buffer (gbm.surface, previous_bo);
}
drmModeSetCrtc (render->fd_drm, render->saved_crtc->crtc_id, render->saved_crtc->buffer_id,
render->saved_crtc->x, render->saved_crtc->y, &render->connector_id, 1, &render->saved_crtc->mode);
drmModeFreeCrtc (render->saved_crtc);
if (previous_bo) {
drmModeRmFB (render->fd_drm, previous_fb);
gbm_surface_release_buffer (gbm.surface, previous_bo);
}
if (render->hdr_blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id);
render->hdr_blob_id = 0;
// eglDestroySurface (display, eglSurface);
eglDestroySurface (eglDisplay, eglSurface);
EglCheck();
gbm_surface_destroy (gbm.surface);
// eglDestroyContext (display, context);
// eglTerminate (display);
eglDestroyContext (eglDisplay, eglContext);
EglCheck();
eglDestroyContext (eglDisplay, eglSharedContext);
EglCheck();
eglTerminate (eglDisplay);
EglCheck();
gbm_device_destroy (gbm.dev);
drmDropMaster(render->fd_drm);
close (render->fd_drm);
free(render);
}

17
hdr.c
View File

@ -330,7 +330,6 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
struct weston_colorspace *cs;
enum hdr_metadata_eotf eotf;
struct hdr_output_metadata data;
static uint32_t blob_id = 0;
int ret,MaxCLL=1500,MaxFALL=400;
int max_lum=4000,min_lum=0050;
struct AVMasteringDisplayMetadata *md = NULL;
@ -378,8 +377,8 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
old_color = color;
old_trc = trc;
if (blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, blob_id);
if (render->hdr_blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id);
switch(trc) {
case AVCOL_TRC_BT709: // 1
@ -468,21 +467,21 @@ static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSid
ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &blob_id);
ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &render->hdr_blob_id);
if (ret) {
printf("DRM: HDR metadata: failed blob create \n");
blob_id = 0;
render->hdr_blob_id = 0;
return;
}
ret = drmModeConnectorSetProperty(render->fd_drm, render->connector_id,
render->hdr_metadata, blob_id);
render->hdr_metadata, render->hdr_blob_id);
if (ret) {
printf("DRM: HDR metadata: failed property set %d\n",ret);
if (blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, blob_id);
blob_id = 0;
if (render->hdr_blob_id)
drmModeDestroyPropertyBlob(render->fd_drm, render->hdr_blob_id);
render->hdr_blob_id = 0;
return;
}
m_need_modeset = 1;

250
video.c
View File

@ -551,6 +551,56 @@ static void X11DPMSReenable(xcb_connection_t *);
static void X11DPMSDisable(xcb_connection_t *);
#endif
char *eglErrorString(EGLint error)
{
switch (error) {
case EGL_SUCCESS:
return "No error";
case EGL_NOT_INITIALIZED:
return "EGL not initialized or failed to initialize";
case EGL_BAD_ACCESS:
return "Resource inaccessible";
case EGL_BAD_ALLOC:
return "Cannot allocate resources";
case EGL_BAD_ATTRIBUTE:
return "Unrecognized attribute or attribute value";
case EGL_BAD_CONTEXT:
return "Invalid EGL context";
case EGL_BAD_CONFIG:
return "Invalid EGL frame buffer configuration";
case EGL_BAD_CURRENT_SURFACE:
return "Current surface is no longer valid";
case EGL_BAD_DISPLAY:
return "Invalid EGL display";
case EGL_BAD_SURFACE:
return "Invalid surface";
case EGL_BAD_MATCH:
return "Inconsistent arguments";
case EGL_BAD_PARAMETER:
return "Invalid argument";
case EGL_BAD_NATIVE_PIXMAP:
return "Invalid native pixmap";
case EGL_BAD_NATIVE_WINDOW:
return "Invalid native window";
case EGL_CONTEXT_LOST:
return "Context lost";
}
return "Unknown error ";
}
///
/// egl check error.
///
#define EglCheck(void) \
{\
EGLint err;\
\
if ((err = eglGetError()) != EGL_SUCCESS) {\
Debug(3, "video/egl: %s:%d error %d %s\n", __FILE__,__LINE__,err,eglErrorString(err));\
}\
}
//----------------------------------------------------------------------------
// DRM Helper Functions
//----------------------------------------------------------------------------
@ -657,6 +707,8 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width, in
#ifdef USE_DRM
get_drm_aspect(&display_aspect_ratio.num,&display_aspect_ratio.den);
#else
Debug(3,"mmHeight %d mm Width %d VideoHeight %d VideoWidth %d\n",VideoScreen->height_in_millimeters,VideoScreen->width_in_millimeters,
VideoScreen->height_in_pixels,VideoScreen->width_in_pixels);
display_aspect_ratio.num = VideoScreen->width_in_pixels * VideoScreen->height_in_millimeters;
display_aspect_ratio.den = VideoScreen->height_in_pixels * VideoScreen->width_in_millimeters;
#endif
@ -829,54 +881,6 @@ static PFNGLXSWAPINTERVALSGIPROC GlxSwapIntervalSGI;
}\
}
char *eglErrorString(EGLint error)
{
switch (error) {
case EGL_SUCCESS:
return "No error";
case EGL_NOT_INITIALIZED:
return "EGL not initialized or failed to initialize";
case EGL_BAD_ACCESS:
return "Resource inaccessible";
case EGL_BAD_ALLOC:
return "Cannot allocate resources";
case EGL_BAD_ATTRIBUTE:
return "Unrecognized attribute or attribute value";
case EGL_BAD_CONTEXT:
return "Invalid EGL context";
case EGL_BAD_CONFIG:
return "Invalid EGL frame buffer configuration";
case EGL_BAD_CURRENT_SURFACE:
return "Current surface is no longer valid";
case EGL_BAD_DISPLAY:
return "Invalid EGL display";
case EGL_BAD_SURFACE:
return "Invalid surface";
case EGL_BAD_MATCH:
return "Inconsistent arguments";
case EGL_BAD_PARAMETER:
return "Invalid argument";
case EGL_BAD_NATIVE_PIXMAP:
return "Invalid native pixmap";
case EGL_BAD_NATIVE_WINDOW:
return "Invalid native window";
case EGL_CONTEXT_LOST:
return "Context lost";
}
return "Unknown error ";
}
///
/// egl check error.
///
#define EglCheck(void) \
{\
EGLint err;\
\
if ((err = eglGetError()) != EGL_SUCCESS) {\
Debug(3, "video/egl: %s:%d error %d %s\n", __FILE__,__LINE__,err,eglErrorString(err));\
}\
}
@ -978,6 +982,7 @@ static void EglInit(void)
XVisualInfo *vi = NULL;
#ifdef PLACEBO
return;
#endif
@ -1016,7 +1021,7 @@ static void EglInit(void)
if (!glXQueryVersion(XlibDisplay, &major, &minor)) {
Fatal(_("video/glx: no GLX support\n"));
}
Info(_("video/glx: glx version %d.%d\n"), major, minor);
Debug(3,"video/glx: glx version %d.%d\n", major, minor);
//
// check which extension are supported
@ -1154,6 +1159,7 @@ static void EglInit(void)
static void EglInit(void)
{
int redSize, greenSize, blueSize, alphaSize;
static int glewdone = 0;
#ifdef PLACEBO
return;
@ -1163,11 +1169,14 @@ static void EglInit(void)
// create egl context
setenv("MESA_GL_VERSION_OVERRIDE","3.3",0);
make_egl();
GLenum err = glewInit();
if (err != GLEW_OK) {
Debug(3, "Error: %s\n", glewGetErrorString(err));
}
if (!glewdone) {
GLenum err = glewInit();
glewdone = 1;
if (err != GLEW_OK) {
Debug(3, "Error: %s\n", glewGetErrorString(err));
}
}
eglGetConfigAttrib(eglDisplay, eglConfig, EGL_BLUE_SIZE, &blueSize);
eglGetConfigAttrib(eglDisplay, eglConfig, EGL_RED_SIZE, &redSize);
@ -1192,7 +1201,7 @@ static void EglInit(void)
static void EglExit(void)
{
Debug(3, "video/egl: %s\n", __FUNCTION__);
#ifdef PLACEBO
#if defined PLACEBO
return;
#endif
@ -1215,11 +1224,7 @@ static void EglExit(void)
GlxCheck();
glxContext = NULL;
}
if (glxThreadContext) {
glXDestroyContext(XlibDisplay, glxThreadContext);
GlxCheck();
glxThreadContext = NULL;
}
if (glxSharedContext) {
glXDestroyContext(XlibDisplay, glxSharedContext);
GlxCheck();
@ -1230,20 +1235,26 @@ static void EglExit(void)
// if currently used, set to none
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
}
#ifndef USE_DRM
if (eglSharedContext) {
eglDestroyContext(eglDisplay, eglSharedContext);
EglCheck();
}
if (eglContext) {
eglDestroyContext(eglDisplay, eglContext);
EglCheck();
eglContext = NULL;
}
if (eglThreadContext) {
eglDestroyContext(eglDisplay, eglThreadContext);
EglCheck();
}
eglTerminate(eglDisplay);
#endif
#ifdef USE_DRM
drm_clean_up();
#endif
#endif
}
#endif
@ -2112,6 +2123,7 @@ static void CuvidDelHwDecoder(CuvidDecoder * decoder)
static int CuvidGlxInit( __attribute__((unused))
const char *display_name)
{
#ifndef PLACEBO
EglInit();
@ -4889,6 +4901,7 @@ void VideoOsdExit(void)
{
OsdDirtyWidth = 0;
OsdDirtyHeight = 0;
VideoOsdClear();
}
//----------------------------------------------------------------------------
@ -5077,29 +5090,7 @@ void pl_log_intern(void *stream, enum pl_log_level level, const char *msg)
printf("%5s: %s\n", prefix[level], msg);
}
void delete_placebo()
{
Debug(3, "delete placebo\n");
if (p == NULL)
return;
if (osdoverlay.plane.texture)
pl_tex_destroy(p->gpu, &osdoverlay.plane.texture);
pl_renderer_destroy(&p->renderer);
if (p->renderertest) {
pl_renderer_destroy(&p->renderertest);
p->renderertest = NULL;
}
pl_swapchain_destroy(&p->swapchain);
vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL);
pl_vk_inst_destroy(&p->vk_inst);
// pl_vulkan_destroy(&p->vk);
pl_context_destroy(&p->ctx);
free(p);
p = NULL;
}
void InitPlacebo()
{
@ -5199,11 +5190,17 @@ void InitPlacebo()
///
/// Video render thread.
///
void delete_decode() {
Debug(3,"decoder thread exit\n");
}
static void *VideoDisplayHandlerThread(void *dummy)
{
prctl(PR_SET_NAME, "cuvid video", 0, 0, 0);
prctl(PR_SET_NAME, "video decode", 0, 0, 0);
sleep(2);
pthread_cleanup_push(delete_decode, NULL);
for (;;) {
// fix dead-lock with CuvidExit
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
@ -5212,10 +5209,49 @@ static void *VideoDisplayHandlerThread(void *dummy)
VideoUsedModule->DisplayHandlerThread();
}
pthread_cleanup_pop(NULL);
return dummy;
}
void exit_display()
{
#ifdef PLACEBO
Debug(3, "delete placebo\n");
if (p == NULL)
return;
if (osdoverlay.plane.texture)
pl_tex_destroy(p->gpu, &osdoverlay.plane.texture);
pl_renderer_destroy(&p->renderer);
if (p->renderertest) {
pl_renderer_destroy(&p->renderertest);
p->renderertest = NULL;
}
pl_swapchain_destroy(&p->swapchain);
vkDestroySurfaceKHR(p->vk_inst->instance, p->pSurface, NULL);
pl_vk_inst_destroy(&p->vk_inst);
// pl_vulkan_destroy(&p->vk);
pl_context_destroy(&p->ctx);
free(p);
p = NULL;
#endif
#ifdef CUVID
if (glxThreadContext) {
glXDestroyContext(XlibDisplay, glxThreadContext);
GlxCheck();
glxThreadContext = NULL;
}
#else
if (eglThreadContext) {
eglDestroyContext(eglDisplay, eglThreadContext);
EglCheck();
eglThreadContext = NULL;
}
#endif
Debug(3,"display thread exit\n");
}
static void *VideoHandlerThread(void *dummy)
{
@ -5224,12 +5260,10 @@ static void *VideoHandlerThread(void *dummy)
EGL_NONE
};
prctl(PR_SET_NAME, "cuvid video display", 0, 0, 0);
prctl(PR_SET_NAME, "video display", 0, 0, 0);
#ifdef PLACEBO
InitPlacebo();
pthread_cleanup_push(delete_placebo, NULL);
#else
#ifdef CUVID
if (EglEnabled) {
@ -5247,21 +5281,21 @@ static void *VideoHandlerThread(void *dummy)
eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglThreadContext);
#endif
#endif
pthread_cleanup_push(exit_display, NULL);
for (;;) {
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
pthread_testcancel();
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
#ifndef USE_DRM
VideoPollEvent();
#endif
// first_time = GetusTicks();
CuvidSyncDisplayFrame();
// printf("syncdisplayframe exec %d\n",(GetusTicks()-first_time)/1000);
}
#ifdef PLACEBO
pthread_cleanup_pop(NULL);
#endif
return dummy;
}
@ -5276,7 +5310,7 @@ static void VideoThreadInit(void)
#ifdef CUVID
glXMakeCurrent(XlibDisplay, None, NULL);
#else
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext);
// eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglContext);
#endif
#endif
pthread_mutex_init(&VideoMutex, NULL);
@ -5301,19 +5335,20 @@ static void VideoThreadExit(void)
// FIXME: can't cancel locked
if (pthread_cancel(VideoThread)) {
Error(_("video: can't queue cancel video display thread\n"));
Debug(3,"video: can't queue cancel video display thread\n");
}
usleep(200000); // 200ms
if (pthread_join(VideoThread, &retval) || retval != PTHREAD_CANCELED) {
Debug(3,"video: can't cancel video decoder thread\n");
}
if (pthread_join(VideoThread, &retval) || retval != PTHREAD_CANCELED) {
Error(_("video: can't cancel video display thread\n"));
}
if (VideoDisplayThread) {
if (pthread_cancel(VideoDisplayThread)) {
Error(_("video: can't queue cancel video display thread\n"));
}
Debug(3,"video: can't queue cancel video display thread\n");
}
usleep(200000); // 200ms
if (pthread_join(VideoDisplayThread, &retval) || retval != PTHREAD_CANCELED) {
Error(_("video: can't cancel video display thread\n"));
Debug(3,"video: can't cancel video display thread\n");
}
VideoDisplayThread = 0;
}
@ -5324,8 +5359,10 @@ static void VideoThreadExit(void)
pthread_mutex_destroy(&OSDMutex);
#ifndef PLACEBO
if (OSDtexture)
glDeleteTextures(1, &OSDtexture);
if (gl_prog_osd) {
glDeleteProgram(gl_prog_osd);
gl_prog_osd = 0;
@ -5334,7 +5371,9 @@ static void VideoThreadExit(void)
glDeleteProgram(gl_prog);
gl_prog = 0;
}
#endif
}
}
@ -6699,6 +6738,7 @@ void VideoExit(void)
if (!XlibDisplay) { // no init or failed
return;
}
//
// Reenable screensaver / DPMS.
//
@ -6751,9 +6791,7 @@ void VideoExit(void)
Connection = 0;
}
#endif
#ifdef USE_DRM
drm_clean_up();
#endif
}
#ifdef USE_DRM
@ -6762,6 +6800,8 @@ int GlxInitopengl () {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE
};
while (!eglSharedContext)
sleep(1);
if (!eglOSDContext) {
eglOSDContext = eglCreateContext(eglDisplay, eglConfig, eglSharedContext, contextAttrs);