diff --git a/Makefile b/Makefile index 6d18474..00479d5 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # # Makefile for a Video Disk Recorder plugin -# +# # $Id: 2a41981a57e5e83036463c6a08c84b86ed9d2be3 $ # The official name of this plugin. @@ -11,13 +11,20 @@ ### Configuration (edit this for your needs) # comment out if not needed -# what kind of driver do we make - -# if VAAPI is enabled the drivername is softhdvaapi -# if CUVID is enabled the drivername is softhdcuvid +# what kind of decoder do we make - +# if VAAPI is enabled the pluginname is softhdvaapi +# if CUVID is enabled the pluginname is softhdcuvid +# if DRM is enabled the pluginname is softhddrm #VAAPI=1 CUVID=1 -# use libplacebo - available for both drivers +# if you enable DRM then the plugin will only run without X server +# only valid for VAAPI +# does not work with libplacebo +#DRM=1 + + +# use libplacebo - available for both decoders but not for DRM #LIBPLACEBO=1 # use YADIF deint - only available with cuvid @@ -25,6 +32,7 @@ CUVID=1 +CONFIG := #-DDEBUG # remove # to enable debug output @@ -60,7 +68,6 @@ SWRESAMPLE = 1 #AVRESAMPLE = 1 #endif -CONFIG := #-DDEBUG #-DOSD_DEBUG # enable debug output+functions CONFIG += -DHAVE_GL # needed for mpv libs #CONFIG += -DSTILL_DEBUG=2 # still picture debug verbose level CONFIG += -DAV_INFO -DAV_INFO_TIME=3000 # info/debug a/v sync @@ -92,7 +99,7 @@ TMPDIR ?= /tmp ### The compiler options: -export CFLAGS = $(call PKGCFG,cflags) +export CFLAGS = $(call PKGCFG,cflags) export CXXFLAGS = $(call PKGCFG,cxxflags) ifeq ($(CFLAGS),) @@ -136,26 +143,34 @@ endif ifeq ($(OPENGL),1) CONFIG += -DUSE_GLX _CFLAGS += $(shell pkg-config --cflags gl glu glew) -#LIBS += $(shell pkg-config --libs glu glew) +#LIBS += $(shell pkg-config --libs glu glew) _CFLAGS += $(shell pkg-config --cflags freetype2) LIBS += $(shell pkg-config --libs freetype2) endif ifeq ($(VAAPI),1) -CONFIG += -DVAAPI +CONFIG += -DVAAPI #LIBPLACEBO=1 PLUGIN = softhdvaapi -LIBS += -lEGL +LIBS += -lEGL endif ifeq ($(LIBPLACEBO),1) CONFIG += -DPLACEBO endif +ifeq ($(DRM),1) +PLUGIN = softhddrm +CONFIG += -DUSE_DRM -DVAAPI +_CFLAGS += $(shell pkg-config --cflags libdrm) +LIBS += -lgbm -ldrm +endif + + ifeq ($(CUVID),1) CONFIG += -DUSE_PIP # PIP support CONFIG += -DCUVID # enable CUVID decoder -LIBS += -lEGL -lGL +LIBS += -lEGL -lGL ifeq ($(YADIF),1) CONFIG += -DYADIF # Yadif only with CUVID endif @@ -173,7 +188,7 @@ SOFILE = libvdr-$(PLUGIN).so # -# Test that libswresample is available +# Test that libswresample is available # #ifneq (exists, $(shell pkg-config libswresample && echo exists)) # $(warning ******************************************************************) @@ -182,7 +197,7 @@ SOFILE = libvdr-$(PLUGIN).so #endif # -# Test and set config for libavutil +# Test and set config for libavutil # ifneq (exists, $(shell pkg-config libavutil && echo exists)) $(warning ******************************************************************) @@ -193,7 +208,7 @@ _CFLAGS += $(shell pkg-config --cflags libavutil) LIBS += $(shell pkg-config --libs libavutil) # -# Test and set config for libswscale +# Test and set config for libswscale # ifneq (exists, $(shell pkg-config libswscale && echo exists)) $(warning ******************************************************************) @@ -233,10 +248,10 @@ endif #_CFLAGS += $(shell pkg-config --cflags libavcodec x11 x11-xcb xcb xcb-icccm) #LIBS += -lrt $(shell pkg-config --libs libavcodec x11 x11-xcb xcb xcb-icccm) -_CFLAGS += $(shell pkg-config --cflags x11 x11-xcb xcb xcb-icccm) -LIBS += -lrt $(shell pkg-config --libs x11 x11-xcb xcb xcb-icccm) +_CFLAGS += $(shell pkg-config --cflags x11 x11-xcb xcb xcb-icccm) +LIBS += -lrt $(shell pkg-config --libs x11 x11-xcb xcb xcb-icccm) -_CFLAGS += -I/usr/local/cuda/include +_CFLAGS += -I/usr/local/cuda/include _CFLAGS += -I./opengl -I./ LIBS += -L/usr/lib64 @@ -247,10 +262,10 @@ LIBS += -lplacebo endif ifeq ($(CUVID),1) -LIBS += -lcuda -L/usr/local/cuda/targets/x86_64-linux/lib -lcudart -lnvcuvid +LIBS += -lcuda -L/usr/local/cuda/targets/x86_64-linux/lib -lcudart -lnvcuvid endif -LIBS += -lGLEW -lGLU -ldl -lglut +LIBS += -lGLEW -lGLU -ldl -lglut ### Includes and Defines (add further entries here): INCLUDES += @@ -261,19 +276,19 @@ DEFINES += -DPLUGIN_NAME_I18N='"$(PLUGIN)"' -D_GNU_SOURCE $(CONFIG) \ ### Make it standard override CXXFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \ - -g -Wextra -Winit-self -Werror=overloaded-virtual -std=c++0x -override CFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \ + -g -W -Wextra -Winit-self -Werror=overloaded-virtual -Wno-unused-parameter +override CFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \ -g -W -Wextra -Winit-self -Wdeclaration-after-statement ### The object files (add further files here): -OBJS = softhdcuvid.o softhddev.o video.o audio.o codec.o ringbuffer.o +OBJS = softhdcuvid.o softhddev.o video.o audio.o codec.o ringbuffer.o ifeq ($(OPENGLOSD),1) -OBJS += openglosd.o +OBJS += openglosd.o endif -SRCS = $(wildcard $(OBJS:.o=.c)) softhdcuvid.cpp +SRCS = $(wildcard $(OBJS:.o=.c)) *.cpp ### The main target: @@ -290,11 +305,11 @@ $(DEPFILE): Makefile ### Internationalization (I18N): -PODIR = po -I18Npo = $(wildcard $(PODIR)/*.po) -I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file)))) +PODIR = po +I18Npo = $(wildcard $(PODIR)/*.po) +I18Nmo = $(addsuffix .mo, $(foreach file, $(I18Npo), $(basename $(file)))) I18Nmsgs = $(addprefix $(DESTDIR)$(LOCDIR)/, $(addsuffix /LC_MESSAGES/vdr-$(PLUGIN).mo, $(notdir $(foreach file, $(I18Npo), $(basename $(file)))))) -I18Npot = $(PODIR)/$(PLUGIN).pot +I18Npot = $(PODIR)/$(PLUGIN).pot %.mo: %.po msgfmt -c -o $@ $< @@ -322,7 +337,7 @@ $(OBJS): Makefile $(SOFILE): $(OBJS) shaders.h - $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@ + $(CXX) $(CXXFLAGS) $(LDFLAGS) -shared $(OBJS) $(LIBS) -o $@ install-lib: $(SOFILE) install -D $^ $(DESTDIR)$(LIBDIR)/$^.$(APIVERSION) @@ -343,11 +358,13 @@ clean: ## Private Targets: -HDRS= $(wildcard *.h) +HDRS= $(wildcard *.h) indent: for i in $(SRCS) $(HDRS); do \ indent $$i; \ + unexpand -a $$i | sed -e s/constconst/const/ > $$i.up; \ + mv $$i.up $$i; \ done video_test: video.c Makefile diff --git a/drm.c b/drm.c new file mode 100644 index 0000000..7c32706 --- /dev/null +++ b/drm.c @@ -0,0 +1,471 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRM_DEBUG + +//---------------------------------------------------------------------------- +// DRM +//---------------------------------------------------------------------------- + +struct _Drm_Render_ +{ + int fd_drm; + drmModeModeInfo mode; + drmModeCrtc *saved_crtc; +// drmEventContext ev; + int bpp; + uint32_t connector_id, crtc_id, video_plane; + uint32_t hdr_metadata; + +}; +typedef struct _Drm_Render_ VideoRender; + +struct { + struct gbm_device *dev; + struct gbm_surface *surface; +} gbm; + +VideoRender *render; + +//---------------------------------------------------------------------------- +// Helper functions +//---------------------------------------------------------------------------- + +static uint64_t GetPropertyValue(int fd_drm, uint32_t objectID, + uint32_t objectType, const char *propName) +{ + uint32_t i; + int found = 0; + uint64_t value = 0; + drmModePropertyPtr Prop; + drmModeObjectPropertiesPtr objectProps = + drmModeObjectGetProperties(fd_drm, objectID, objectType); + + for (i = 0; i < objectProps->count_props; i++) { + if ((Prop = drmModeGetProperty(fd_drm, objectProps->props[i])) == NULL) + fprintf(stderr, "GetPropertyValue: Unable to query property.\n"); + + if (strcmp(propName, Prop->name) == 0) { + value = objectProps->prop_values[i]; + found = 1; + } + + drmModeFreeProperty(Prop); + + if (found) + break; + } + + drmModeFreeObjectProperties(objectProps); + +#ifdef DRM_DEBUG + if (!found) + fprintf(stderr, "GetPropertyValue: Unable to find value for property \'%s\'.\n", + propName); +#endif + return value; +} +static uint32_t GetPropertyID(int fd_drm, uint32_t objectID, + uint32_t objectType, const char *propName) +{ + uint32_t i; + int found = 0; + uint32_t value = -1; + drmModePropertyPtr Prop; + drmModeObjectPropertiesPtr objectProps = + drmModeObjectGetProperties(fd_drm, objectID, objectType); + + for (i = 0; i < objectProps->count_props; i++) { + if ((Prop = drmModeGetProperty(fd_drm, objectProps->props[i])) == NULL) + fprintf(stderr, "GetPropertyValue: Unable to query property.\n"); + + if (strcmp(propName, Prop->name) == 0) { + value = objectProps->props[i]; + found = 1; + } + drmModeFreeProperty(Prop); + if (found) + break; + } + drmModeFreeObjectProperties(objectProps); + +#ifdef DRM_DEBUG + if (!found) + Debug(3,"GetPropertyValue: Unable to find ID for property \'%s\'.\n",propName); +#endif + return value; +} + +static int SetPropertyRequest(drmModeAtomicReqPtr ModeReq, int fd_drm, + uint32_t objectID, uint32_t objectType, + const char *propName, uint64_t value) +{ + uint32_t i; + uint64_t id = 0; + drmModePropertyPtr Prop; + drmModeObjectPropertiesPtr objectProps = + drmModeObjectGetProperties(fd_drm, objectID, objectType); + + for (i = 0; i < objectProps->count_props; i++) { + if ((Prop = drmModeGetProperty(fd_drm, objectProps->props[i])) == NULL) + printf( "SetPropertyRequest: Unable to query property.\n"); + + if (strcmp(propName, Prop->name) == 0) { + id = Prop->prop_id; + drmModeFreeProperty(Prop); + break; + } + + drmModeFreeProperty(Prop); + } + + drmModeFreeObjectProperties(objectProps); + + if (id == 0) + printf( "SetPropertyRequest: Unable to find value for property \'%s\'.\n", + propName); + + return drmModeAtomicAddProperty(ModeReq, objectID, id, value); +} + +static int FindDevice(VideoRender * render) +{ + drmVersion *version; + drmModeRes *resources; + drmModeConnector *connector; + drmModeEncoder *encoder = 0; + drmModeModeInfo *mode; + drmModePlane *plane; + drmModePlaneRes *plane_res; + drmModeObjectPropertiesPtr props; + uint32_t j, k; + uint64_t has_dumb; + uint64_t has_prime; + int i,ii=0; + + render->fd_drm = open("/dev/dri/card0", O_RDWR); + if (render->fd_drm < 0) { + fprintf(stderr, "FindDevice: cannot open /dev/dri/card0: %m\n"); + return -errno; + } + + + version = drmGetVersion(render->fd_drm); + fprintf(stderr, "FindDevice: open /dev/dri/card0: %i %s\n", version->name_len, version->name); + + // check capability + if (drmGetCap(render->fd_drm, DRM_CAP_DUMB_BUFFER, &has_dumb) < 0 || has_dumb == 0) + fprintf(stderr, "FindDevice: drmGetCap DRM_CAP_DUMB_BUFFER failed or doesn't have dumb buffer\n"); + + if (drmSetClientCap(render->fd_drm, DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1) != 0) + fprintf(stderr, "FindDevice: DRM_CLIENT_CAP_UNIVERSAL_PLANES not available.\n"); + + if (drmSetClientCap(render->fd_drm, DRM_CLIENT_CAP_ATOMIC, 1) != 0) + fprintf(stderr, "FindDevice: DRM_CLIENT_CAP_ATOMIC not available.\n"); + + if (drmGetCap(render->fd_drm, DRM_CAP_PRIME, &has_prime) < 0) + fprintf(stderr, "FindDevice: DRM_CAP_PRIME not available.\n"); + + if (drmGetCap(render->fd_drm, DRM_PRIME_CAP_EXPORT, &has_prime) < 0) + fprintf(stderr, "FindDevice: DRM_PRIME_CAP_EXPORT not available.\n"); + + if (drmGetCap(render->fd_drm, DRM_PRIME_CAP_IMPORT, &has_prime) < 0) + fprintf(stderr, "FindDevice: DRM_PRIME_CAP_IMPORT not available.\n"); + + if ((resources = drmModeGetResources(render->fd_drm)) == NULL){ + fprintf(stderr, "FindDevice: cannot retrieve DRM resources (%d): %m\n", errno); + return -errno; + } + +#ifdef DEBUG + Debug(3,"[FindDevice] DRM have %i connectors, %i crtcs, %i encoders\n", + resources->count_connectors, resources->count_crtcs, + resources->count_encoders); +#endif + + // find all available connectors + for (i = 0; i < resources->count_connectors; i++) { + connector = drmModeGetConnector(render->fd_drm, resources->connectors[i]); + if (!connector) { + fprintf(stderr, "FindDevice: cannot retrieve DRM connector (%d): %m\n", errno); + return -errno; + } + + if (connector->connection == DRM_MODE_CONNECTED && connector->count_modes > 0) { + render->connector_id = connector->connector_id; + + // FIXME: use default encoder/crtc pair + if ((encoder = drmModeGetEncoder(render->fd_drm, connector->encoder_id)) == NULL){ + fprintf(stderr, "FindDevice: cannot retrieve encoder (%d): %m\n", errno); + return -errno; + } + render->crtc_id = encoder->crtc_id; + + render->hdr_metadata = GetPropertyID(render->fd_drm, connector->connector_id, + DRM_MODE_OBJECT_CONNECTOR, "HDR_OUTPUT_METADATA"); + printf("ID %d of METADATA in Connector %d connected %d\n",render->hdr_metadata,connector->connector_id,connector->connection); + + memcpy(&render->mode, &connector->modes[0], sizeof(drmModeModeInfo)); // set fallback + // search Modes for Connector + for (ii = 0; ii < connector->count_modes; ii++) { + mode = &connector->modes[ii]; + printf("Mode %d %dx%d Rate %d\n",ii,mode->hdisplay,mode->vdisplay,mode->vrefresh); + if (VideoWindowWidth && VideoWindowHeight) { // preset by command line + if (VideoWindowWidth == mode->hdisplay && + VideoWindowHeight == mode->vdisplay && + mode->vrefresh == 50 && + !(mode->flags & DRM_MODE_FLAG_INTERLACE)) { + memcpy(&render->mode, mode, sizeof(drmModeModeInfo)); + break; + } + } + else { + if (!(mode->flags & DRM_MODE_FLAG_INTERLACE)) { + memcpy(&render->mode, mode, sizeof(drmModeModeInfo)); + VideoWindowWidth = mode->hdisplay; + VideoWindowHeight = mode->vdisplay; + break; + } + } + } + i = resources->count_connectors; // uuuuhh + } + VideoWindowWidth = render->mode.hdisplay; + VideoWindowHeight = render->mode.vdisplay; + printf("Use Mode %d %dx%d Rate %d\n",ii,render->mode.hdisplay,render->mode.vdisplay,render->mode.vrefresh); + drmModeFreeConnector(connector); + } + + // find first plane + if ((plane_res = drmModeGetPlaneResources(render->fd_drm)) == NULL) + fprintf(stderr, "FindDevice: cannot retrieve PlaneResources (%d): %m\n", errno); + + for (j = 0; j < plane_res->count_planes; j++) { + plane = drmModeGetPlane(render->fd_drm, plane_res->planes[j]); + + if (plane == NULL) + fprintf(stderr, "FindDevice: cannot query DRM-KMS plane %d\n", j); + + for (i = 0; i < resources->count_crtcs; i++) { + if (plane->possible_crtcs & (1 << i)) + break; + } + + uint64_t type = GetPropertyValue(render->fd_drm, plane_res->planes[j], + DRM_MODE_OBJECT_PLANE, "type"); + uint64_t zpos = 0; + +#ifdef DRM_DEBUG // If more then 2 crtcs this must rewriten!!! + printf("[FindDevice] Plane id %i crtc_id %i possible_crtcs %i possible CRTC %i type %s\n", + plane->plane_id, plane->crtc_id, plane->possible_crtcs, resources->crtcs[i], + (type == DRM_PLANE_TYPE_PRIMARY) ? "primary plane" : + (type == DRM_PLANE_TYPE_OVERLAY) ? "overlay plane" : + (type == DRM_PLANE_TYPE_CURSOR) ? "cursor plane" : "No plane type"); +#endif + + // test pixel format and plane caps + for (k = 0; k < plane->count_formats; k++) { + if (encoder->possible_crtcs & plane->possible_crtcs) { + switch (plane->formats[k]) { + case DRM_FORMAT_XRGB2101010: + if (!render->video_plane) { + render->video_plane = plane->plane_id; + } + break; + default: + break; + } + } + } + drmModeFreePlane(plane); + } + + drmModeFreePlaneResources(plane_res); + + drmModeFreeEncoder(encoder); + drmModeFreeResources(resources); + +#ifdef DRM_DEBUG + printf("[FindDevice] DRM setup CRTC: %i video_plane: %i \n", + render->crtc_id, render->video_plane); +#endif + + // save actual modesetting + render->saved_crtc = drmModeGetCrtc(render->fd_drm, render->crtc_id); + + return 0; +} + + + +/// +/// Initialize video output module. +/// +void VideoInitDrm() +{ + int i; + + if (!(render = calloc(1, sizeof(*render)))) { + Error(_("video/DRM: out of memory\n")); + return; + } + + if (FindDevice(render)){ + fprintf(stderr, "VideoInit: FindDevice() failed\n"); + } + + gbm.dev = gbm_create_device (render->fd_drm); + assert (gbm.dev != NULL); + + PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display = NULL; + get_platform_display = + (void *) eglGetProcAddress("eglGetPlatformDisplayEXT"); + assert(get_platform_display != NULL); + + eglDisplay = get_platform_display(EGL_PLATFORM_GBM_KHR, gbm.dev, NULL); + + assert (eglDisplay != NULL); +// return; + + drmModeAtomicReqPtr ModeReq; + const uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; + uint32_t modeID = 0; + + if (drmModeCreatePropertyBlob(render->fd_drm, &render->mode, sizeof(render->mode), &modeID) != 0) { + fprintf(stderr, "Failed to create mode property.\n"); + return; + } + if (!(ModeReq = drmModeAtomicAlloc())) { + fprintf(stderr, "cannot allocate atomic request (%d): %m\n", errno); + return; + } + + SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, + DRM_MODE_OBJECT_CRTC, "MODE_ID", modeID); + SetPropertyRequest(ModeReq, render->fd_drm, render->connector_id, + DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", render->crtc_id); + SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, + DRM_MODE_OBJECT_CRTC, "ACTIVE", 1); + + if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0) + 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); + + drmModeAtomicFree(ModeReq); + +} + + +struct gbm_bo *bo = NULL, *next_bo=NULL; +struct drm_fb *fb; +static int m_need_modeset = 0; +static int old_color=-1,old_trc=-1; + +void InitBo(int bpp) { + // create the GBM and EGL surface + render->bpp = bpp; + gbm.surface = gbm_surface_create (gbm.dev, VideoWindowWidth,VideoWindowHeight, + bpp==10?GBM_FORMAT_XRGB2101010:GBM_FORMAT_ARGB8888, + GBM_BO_USE_SCANOUT|GBM_BO_USE_RENDERING); + assert(gbm.surface != NULL); + eglSurface = eglCreateWindowSurface (eglDisplay, eglConfig, gbm.surface, NULL); + assert(eglSurface != NULL); +} + +static struct gbm_bo *previous_bo = NULL; +static uint32_t previous_fb; + +static void drm_swap_buffers () { + + uint32_t fb; + + eglSwapBuffers (eglDisplay, eglSurface); + struct gbm_bo *bo = gbm_surface_lock_front_buffer (gbm.surface); +#if 1 + if (bo == NULL) + bo = gbm_surface_lock_front_buffer (gbm.surface); +#endif + assert (bo != NULL); + uint32_t handle = gbm_bo_get_handle (bo).u32; + uint32_t pitch = gbm_bo_get_stride (bo); + + + drmModeAddFB (render->fd_drm, VideoWindowWidth,VideoWindowHeight,render->bpp==10? 30:24, 32, pitch, handle, &fb); +// drmModeSetCrtc (render->fd_drm, render->crtc_id, fb, 0, 0, &render->connector_id, 1, &render->mode); + + if (m_need_modeset) { + drmModeAtomicReqPtr ModeReq; + const uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET; + uint32_t modeID = 0; + + if (drmModeCreatePropertyBlob(render->fd_drm, &render->mode, sizeof(render->mode), &modeID) != 0) { + fprintf(stderr, "Failed to create mode property.\n"); + return; + } + if (!(ModeReq = drmModeAtomicAlloc())) { + fprintf(stderr, "cannot allocate atomic request (%d): %m\n", errno); + return; + } + + // Need to disable the CRTC in order to submit the HDR data.... + SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, + DRM_MODE_OBJECT_CRTC, "ACTIVE", 0); + if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0) + fprintf(stderr, "cannot set atomic mode (%d): %m\n", errno); + sleep(2); + + SetPropertyRequest(ModeReq, render->fd_drm, render->connector_id, + DRM_MODE_OBJECT_CONNECTOR, "Colorspace",old_color==AVCOL_PRI_BT2020?9:2 ); + SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, + DRM_MODE_OBJECT_CRTC, "MODE_ID", modeID); + SetPropertyRequest(ModeReq, render->fd_drm, render->connector_id, + DRM_MODE_OBJECT_CONNECTOR, "CRTC_ID", render->crtc_id); + SetPropertyRequest(ModeReq, render->fd_drm, render->crtc_id, + DRM_MODE_OBJECT_CRTC, "ACTIVE", 1); + + if (drmModeAtomicCommit(render->fd_drm, ModeReq, flags, NULL) != 0) + 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); + + drmModeAtomicFree(ModeReq); + m_need_modeset = 0; + } + drmModeSetCrtc (render->fd_drm, render->crtc_id, fb, 0, 0, &render->connector_id, 1, &render->mode); + + if (previous_bo) { + drmModeRmFB (render->fd_drm, previous_fb); + gbm_surface_release_buffer (gbm.surface, previous_bo); + } + previous_bo = bo; + previous_fb = fb; +} + +static void drm_clean_up () { + // set the previous crtc + + 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); + } + +// eglDestroySurface (display, eglSurface); + gbm_surface_destroy (gbm.surface); +// eglDestroyContext (display, context); +// eglTerminate (display); + gbm_device_destroy (gbm.dev); + close (render->fd_drm); +} diff --git a/hdr.c b/hdr.c new file mode 100644 index 0000000..bd73d7a --- /dev/null +++ b/hdr.c @@ -0,0 +1,491 @@ +#include + +/** + * struct hdr_metadata_infoframe - HDR Metadata Infoframe Data. + * + * HDR Metadata Infoframe as per CTA 861.G spec. This is expected + * to match exactly with the spec. + * + * Userspace is expected to pass the metadata information as per + * the format described in this structure. + */ +struct hdr_metadata_infoframe { + /** + * @eotf: Electro-Optical Transfer Function (EOTF) + * used in the stream. + */ + __u8 eotf; + /** + * @metadata_type: Static_Metadata_Descriptor_ID. + */ + __u8 metadata_type; + /** + * @display_primaries: Color Primaries of the Data. + * These are coded as unsigned 16-bit values in units of + * 0.00002, where 0x0000 represents zero and 0xC350 + * represents 1.0000. + * @display_primaries.x: X cordinate of color primary. + * @display_primaries.y: Y cordinate of color primary. + */ + struct { + __u16 x, y; + } display_primaries[3]; + /** + * @white_point: White Point of Colorspace Data. + * These are coded as unsigned 16-bit values in units of + * 0.00002, where 0x0000 represents zero and 0xC350 + * represents 1.0000. + * @white_point.x: X cordinate of whitepoint of color primary. + * @white_point.y: Y cordinate of whitepoint of color primary. + */ + struct { + __u16 x, y; + } white_point; + /** + * @max_display_mastering_luminance: Max Mastering Display Luminance. + * This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + */ + __u16 max_display_mastering_luminance; + /** + * @min_display_mastering_luminance: Min Mastering Display Luminance. + * This value is coded as an unsigned 16-bit value in units of + * 0.0001 cd/m2, where 0x0001 represents 0.0001 cd/m2 and 0xFFFF + * represents 6.5535 cd/m2. + */ + __u16 min_display_mastering_luminance; + /** + * @max_cll: Max Content Light Level. + * This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + */ + __u16 max_cll; + /** + * @max_fall: Max Frame Average Light Level. + * This value is coded as an unsigned 16-bit value in units of 1 cd/m2, + * where 0x0001 represents 1 cd/m2 and 0xFFFF represents 65535 cd/m2. + */ + __u16 max_fall; +}; + +/** + * struct hdr_output_metadata - HDR output metadata + * + * Metadata Information to be passed from userspace + */ +struct hdr_output_metadata { + /** + * @metadata_type: Static_Metadata_Descriptor_ID. + */ + __u32 metadata_type; + /** + * @hdmi_metadata_type1: HDR Metadata Infoframe. + */ + union { + struct hdr_metadata_infoframe hdmi_metadata_type1; + }; +}; + + + +enum hdr_metadata_eotf { + EOTF_TRADITIONAL_GAMMA_SDR, + EOTF_TRADITIONAL_GAMMA_HDR, + EOTF_ST2084, + EOTF_HLG, +}; + + +enum metadata_id { + METADATA_TYPE1, +}; + +void +weston_hdr_metadata(void *data, + uint16_t display_primary_r_x, + uint16_t display_primary_r_y, + uint16_t display_primary_g_x, + uint16_t display_primary_g_y, + uint16_t display_primary_b_x, + uint16_t display_primary_b_y, + uint16_t white_point_x, + uint16_t white_point_y, + uint16_t min_luminance, + uint16_t max_luminance, + uint16_t max_cll, + uint16_t max_fall, + enum hdr_metadata_eotf eotf) +{ + uint8_t *data8; + uint16_t *data16; + + data8 = data; + + *data8++ = eotf; + *data8++ = METADATA_TYPE1; + + data16 = (void*)data8; + + *data16++ = display_primary_r_x; + *data16++ = display_primary_r_y; + *data16++ = display_primary_g_x; + *data16++ = display_primary_g_y; + *data16++ = display_primary_b_x; + *data16++ = display_primary_b_y; + *data16++ = white_point_x; + *data16++ = white_point_y; + + *data16++ = max_luminance; + *data16++ = min_luminance; + *data16++ = max_cll; + *data16++ = max_fall; +} + +struct weston_vector { + float f[4]; +}; + +struct weston_colorspace { + struct weston_vector r, g, b; + struct weston_vector whitepoint; + const char *name; + const char *whitepoint_name; +}; + +struct weston_colorspace hdr10; + +static const struct weston_colorspace bt470m = { + .r = {{ 0.670f, 0.330f, }}, + .g = {{ 0.210f, 0.710f, }}, + .b = {{ 0.140f, 0.080f, }}, + .whitepoint = {{ 0.3101f, 0.3162f, }}, + .name = "BT.470 M", + .whitepoint_name = "C", +}; + +static const struct weston_colorspace bt470bg = { + .r = {{ 0.640f, 0.330f, }}, + .g = {{ 0.290f, 0.600f, }}, + .b = {{ 0.150f, 0.060f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "BT.470 B/G", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace smpte170m = { + .r = {{ 0.630f, 0.340f, }}, + .g = {{ 0.310f, 0.595f, }}, + .b = {{ 0.155f, 0.070f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "SMPTE 170M", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace smpte240m = { + .r = {{ 0.630f, 0.340f, }}, + .g = {{ 0.310f, 0.595f, }}, + .b = {{ 0.155f, 0.070f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "SMPTE 240M", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace bt709 = { + .r = {{ 0.640f, 0.330f, }}, + .g = {{ 0.300f, 0.600f, }}, + .b = {{ 0.150f, 0.060f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "BT.709", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace bt2020 = { + .r = {{ 0.708f, 0.292f, }}, + .g = {{ 0.170f, 0.797f, }}, + .b = {{ 0.131f, 0.046f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "BT.2020", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace srgb = { + .r = {{ 0.640f, 0.330f, }}, + .g = {{ 0.300f, 0.600f, }}, + .b = {{ 0.150f, 0.060f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "sRGB", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace adobergb = { + .r = {{ 0.640f, 0.330f, }}, + .g = {{ 0.210f, 0.710f, }}, + .b = {{ 0.150f, 0.060f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "AdobeRGB", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace dci_p3 = { + .r = {{ 0.680f, 0.320f, }}, + .g = {{ 0.265f, 0.690f, }}, + .b = {{ 0.150f, 0.060f, }}, + .whitepoint = {{ 0.3127f, 0.3290f, }}, + .name = "DCI-P3 D65", + .whitepoint_name = "D65", +}; + +static const struct weston_colorspace prophotorgb = { + .r = {{ 0.7347f, 0.2653f, }}, + .g = {{ 0.1596f, 0.8404f, }}, + .b = {{ 0.0366f, 0.0001f, }}, + .whitepoint = {{ .3457, .3585 }}, + .name = "ProPhoto RGB", + .whitepoint_name = "D50", +}; + +static const struct weston_colorspace ciergb = { + .r = {{ 0.7347f, 0.2653f, }}, + .g = {{ 0.2738f, 0.7174f, }}, + .b = {{ 0.1666f, 0.0089f, }}, + .whitepoint = {{ 1.0f / 3.0f, 1.0f / 3.0f, }}, + .name = "CIE RGB", + .whitepoint_name = "E", +}; + +static const struct weston_colorspace ciexyz = { + .r = {{ 1.0f, 0.0f, }}, + .g = {{ 0.0f, 1.0f, }}, + .b = {{ 0.0f, 0.0f, }}, + .whitepoint = {{ 1.0f / 3.0f, 1.0f / 3.0f, }}, + .name = "CIE XYZ", + .whitepoint_name = "E", +}; + +const struct weston_colorspace ap0 = { + .r = {{ 0.7347f, 0.2653f, }}, + .g = {{ 0.0000f, 1.0000f, }}, + .b = {{ 0.0001f, -0.0770f, }}, + .whitepoint = {{ .32168f, .33767f, }}, + .name = "ACES primaries #0", + .whitepoint_name = "D60", +}; + +const struct weston_colorspace ap1 = { + .r = {{ 0.713f, 0.393f, }}, + .g = {{ 0.165f, 0.830f, }}, + .b = {{ 0.128f, 0.044f, }}, + .whitepoint = {{ 0.32168f, 0.33767f, }}, + .name = "ACES primaries #1", + .whitepoint_name = "D60", +}; + +static const struct weston_colorspace * const colorspaces[] = { + &bt470m, + &bt470bg, + &smpte170m, + &smpte240m, + &bt709, + &bt2020, + &srgb, + &adobergb, + &dci_p3, + &prophotorgb, + &ciergb, + &ciexyz, + &ap0, + &ap1, +}; +#define ARRAY_LENGTH(a) (sizeof(a) / sizeof(a)[0]) +const struct weston_colorspace * +weston_colorspace_lookup(const char *name) +{ + unsigned i; + + if (!name) + return NULL; + + for (i = 0; i < ARRAY_LENGTH(colorspaces); i++) { + const struct weston_colorspace *c = colorspaces[i]; + + if (!strcmp(c->name, name)) + return c; + } + + return NULL; +} + +static int cleanup=0; + + +static uint16_t encode_xyy(float xyy) +{ + return xyy * 50000; +} +static AVMasteringDisplayMetadata md_save = {0}; +static AVContentLightMetadata ld_save = {0}; +static void set_hdr_metadata(int color,int trc, AVFrameSideData *sd1, AVFrameSideData *sd2) +{ + drmModeAtomicReqPtr ModeReq; + 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; + struct AVContentLightMetadata *ld = NULL; + + if (render->hdr_metadata == -1) { // Metadata not supported + return; + } + + // clean up FFMEPG stuff + if (trc == AVCOL_TRC_BT2020_10) + trc = AVCOL_TRC_ARIB_STD_B67; + if (trc == AVCOL_TRC_UNSPECIFIED) + trc = AVCOL_TRC_BT709; + if (color == AVCOL_PRI_UNSPECIFIED) + color = AVCOL_PRI_BT709; + + if ((old_color == color && old_trc == trc && !sd1 && !sd2) || !render->hdr_metadata) + return; // nothing to do + + if (sd1) + md = sd1->data; + + if (sd2) + ld = sd2->data; + + if (md && !memcmp(md,&md_save,sizeof(md_save))) + if (ld && !memcmp(ld,&ld_save,sizeof(ld_save))) { + return; + } + else if (ld && !memcmp(ld,&ld_save,sizeof(ld_save))) { + return; + } + + if (ld) + memcpy(&ld_save,ld,sizeof(ld_save)); + if (md) + memcpy(&md_save,md,sizeof(md_save)); + + printf("Update HDR to TRC %d color %d\n",trc,color); + + if (trc == AVCOL_TRC_BT2020_10) + trc = AVCOL_TRC_ARIB_STD_B67; + + old_color = color; + old_trc = trc; + + if (blob_id) + drmModeDestroyPropertyBlob(render->fd_drm, blob_id); + + switch(trc) { + case AVCOL_TRC_BT709: // 1 + case AVCOL_TRC_UNSPECIFIED: // 2 + eotf = EOTF_TRADITIONAL_GAMMA_SDR; + break; + case AVCOL_TRC_BT2020_10: // 14 + case AVCOL_TRC_BT2020_12: + case AVCOL_TRC_ARIB_STD_B67: // 18 HLG + eotf = EOTF_HLG; + break; + case AVCOL_TRC_SMPTE2084: // 16 + eotf = EOTF_ST2084; + default: + eotf = EOTF_TRADITIONAL_GAMMA_SDR; + break; + } + + switch (color) { + case AVCOL_PRI_BT709: // 1 + case AVCOL_PRI_UNSPECIFIED: // 2 + cs = weston_colorspace_lookup("BT.709"); + break; + case AVCOL_PRI_BT2020: // 9 + cs = weston_colorspace_lookup("BT.2020"); + break; + case AVCOL_PRI_BT470BG: // 5 + cs = weston_colorspace_lookup("BT.470 B/G"); // BT.601 + break; + default: + cs = weston_colorspace_lookup("BT.709"); + break; + } + + if (md) { // we got Metadata + if (md->has_primaries) { + Debug(3,"Mastering Display Metadata,\n has_primaries:%d has_luminance:%d \n" + "r(%5.4f,%5.4f) g(%5.4f,%5.4f) b(%5.4f %5.4f) wp(%5.4f, %5.4f) \n" + "min_luminance=%f, max_luminance=%f\n", + md->has_primaries, md->has_luminance, + av_q2d(md->display_primaries[0][0]), + av_q2d(md->display_primaries[0][1]), + av_q2d(md->display_primaries[1][0]), + av_q2d(md->display_primaries[1][1]), + av_q2d(md->display_primaries[2][0]), + av_q2d(md->display_primaries[2][1]), + av_q2d(md->white_point[0]), av_q2d(md->white_point[1]), + av_q2d(md->min_luminance), av_q2d(md->max_luminance)); + + cs = &hdr10; + cs->r.f[0] = (float)md->display_primaries[0][0].num / (float)md->display_primaries[0][0].den; + cs->r.f[1] = (float)md->display_primaries[0][1].num / (float)md->display_primaries[0][1].den; + cs->g.f[0] = (float)md->display_primaries[1][0].num / (float)md->display_primaries[1][0].den; + cs->g.f[1] = (float)md->display_primaries[1][1].num / (float)md->display_primaries[1][1].den; + cs->b.f[0] = (float)md->display_primaries[2][0].num / (float)md->display_primaries[2][0].den; + cs->b.f[1] = (float)md->display_primaries[2][1].num / (float)md->display_primaries[2][1].den; + cs->whitepoint.f[0] = (float)md->white_point[0].num / (float)md->white_point[0].den; + cs->whitepoint.f[1] = (float)md->white_point[1].num / (float)md->white_point[1].den; + } + if (md->has_luminance) { + max_lum = av_q2d(md->max_luminance); + min_lum = av_q2d(md->min_luminance) * 10000 ; + printf("max_lum %d min_lum %d\n",max_lum,min_lum); + } + } + if (ld) { + Debug(3,"Has MaxCLL %d MaxFALL %d\n",ld->MaxCLL,ld->MaxFALL); + MaxCLL = ld->MaxCLL; + MaxFALL = ld->MaxFALL; + } + data.metadata_type = 7; // ???????????????????????? + weston_hdr_metadata(&data.hdmi_metadata_type1, + encode_xyy(cs->r.f[0]), + encode_xyy(cs->r.f[1]), + encode_xyy(cs->g.f[0]), + encode_xyy(cs->g.f[1]), + encode_xyy(cs->b.f[0]), + encode_xyy(cs->b.f[1]), + encode_xyy(cs->whitepoint.f[0]), + encode_xyy(cs->whitepoint.f[1]), + max_lum, // max_display_mastering_luminance + min_lum, // min_display_mastering_luminance + MaxCLL, // Maximum Content Light Level (MaxCLL) + MaxFALL, // Maximum Frame-Average Light Level (MaxFALL) + eotf); + + + + ret = drmModeCreatePropertyBlob(render->fd_drm, &data, sizeof(data), &blob_id); + if (ret) { + printf("DRM: HDR metadata: failed blob create \n"); + return; + } + + ret = drmModeConnectorSetProperty(render->fd_drm, render->connector_id, + render->hdr_metadata, blob_id); + if (ret) { + printf("DRM: HDR metadata: failed property set %d\n",ret); + + if (blob_id) + drmModeDestroyPropertyBlob(render->fd_drm, blob_id); + return; + } + m_need_modeset = 1; + + printf("DRM: HDR metadata: prop set\n"); + +} + diff --git a/openglosd.cpp b/openglosd.cpp index a47cd7d..e56aaa4 100644 --- a/openglosd.cpp +++ b/openglosd.cpp @@ -220,6 +220,18 @@ void main() \ } \ "; #endif +/// +/// GLX check error. +/// +#define GlxCheck(void)\ +{\ + GLenum err;\ +\ + if ((err = glGetError()) != GL_NO_ERROR) {\ + esyslog( "video/glx: error %s:%d %d '%s'\n",__FILE__,__LINE__, err, gluErrorString(err));\ + }\ +} + static cShader *Shaders[stCount]; void cShader::Use(void) { @@ -322,14 +334,14 @@ bool cShader::CheckCompileErrors(GLuint object, bool program) { glGetShaderiv(object, GL_COMPILE_STATUS, &success); if (!success) { glGetShaderInfoLog(object, 1024, NULL, infoLog); - esyslog("[softhddev]:SHADER: Compile-time error: Type: %d - \n%s\n", type, infoLog); + esyslog("\n[softhddev]:SHADER: Compile-time error: Type: %d - \n>%s<\n", type, infoLog); return false; } } else { glGetProgramiv(object, GL_LINK_STATUS, &success); if (!success) { glGetProgramInfoLog(object, 1024, NULL, infoLog); - esyslog("[softhddev]:SHADER: Link-time error: Type: %d - \n%s\n", type, infoLog); + esyslog("[softhddev]:SHADER: Link-time error: Type: %d - \n>%s<\n", type, infoLog); return false; } } @@ -398,7 +410,8 @@ void cOglGlyph::LoadTexture(FT_BitmapGlyph ftGlyph) { } - +extern "C" void GlxInitopengl(); +extern "C" void GlxDrawopengl(); /**************************************************************************************** * cOglFont ****************************************************************************************/ @@ -439,7 +452,7 @@ cOglFont *cOglFont::Get(const char *name, int charHeight) { } void cOglFont::Init(void) { - + if (FT_Init_FreeType(&ftLib)) { esyslog("[softhddev]failed to initialize FreeType library!"); return; @@ -1273,8 +1286,9 @@ bool cOglCmdDrawText::Execute(void) { esyslog("[softhddev]ERROR: could not load glyph %x", sym); } - if ( limitX && xGlyph + g->AdvanceX() > limitX ) + if ( limitX && xGlyph + g->AdvanceX() > limitX ) { break; + } kerning = f->Kerning(g, prevSym); prevSym = sym; @@ -1320,6 +1334,7 @@ cOglCmdDrawImage::cOglCmdDrawImage(cOglFb *fb, tColor *argb, GLint width, GLint this->overlay = overlay; this->scaleX = scaleX; this->scaleY = scaleY; + } cOglCmdDrawImage::~cOglCmdDrawImage(void) { @@ -1328,7 +1343,10 @@ cOglCmdDrawImage::~cOglCmdDrawImage(void) { bool cOglCmdDrawImage::Execute(void) { GLuint texture; - +#ifdef USE_DRM + GlxDrawopengl(); // here we need the Shared Context for upload + GlxCheck(); +#endif glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexImage2D( @@ -1347,7 +1365,10 @@ bool cOglCmdDrawImage::Execute(void) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); - +#ifdef USE_DRM + GlxInitopengl(); // Reset Context + GlxCheck(); +#endif GLfloat x1 = x; //left GLfloat y1 = y; //top @@ -1479,6 +1500,7 @@ bool cOglCmdDropImage::Execute(void) { cOglThread::cOglThread(cCondWait *startWait, int maxCacheSize) : cThread("oglThread") { stalled = false; memCached = 0; + this->maxCacheSize = maxCacheSize * 1024 * 1024; this->startWait = startWait; wait = new cCondWait(); @@ -1491,6 +1513,7 @@ cOglThread::cOglThread(cCondWait *startWait, int maxCacheSize) : cThread("oglThr } Start(); + } cOglThread::~cOglThread() { @@ -1689,13 +1712,12 @@ void cOglThread::Action(void) { dsyslog("[softhddev]OpenGL Worker Thread Ended"); } -extern "C" int GlxInitopengl(); - - bool cOglThread::InitOpenGL(void) { - +#ifdef USE_DRM + GlxInitopengl(); +#else const char *displayName = X11DisplayName; if (!displayName) { displayName = getenv("DISPLAY"); @@ -1728,7 +1750,8 @@ bool cOglThread::InitOpenGL(void) { esyslog("[softhddev]glewInit failed, aborting\n"); return false; } - +#endif + VertexBuffers[vbText]->EnableBlending(); glDisable(GL_DEPTH_TEST); return true; @@ -1790,8 +1813,9 @@ void cOglThread::Cleanup(void) { DeleteShaders(); // glVDPAUFiniNV(); cOglFont::Cleanup(); +#ifndef USE_DRM glutExit(); - +#endif pthread_mutex_unlock(&OSDMutex); } diff --git a/softhdcuvid.cpp b/softhdcuvid.cpp index 33a290e..519195c 100644 --- a/softhdcuvid.cpp +++ b/softhdcuvid.cpp @@ -61,7 +61,7 @@ extern "C" /// vdr-plugin version number. /// Makefile extracts the version number for generating the file name /// for the distribution archive. -static const char *const VERSION = "2.1.0" +static const char *const VERSION = "3.0.0" #ifdef GIT_REV "-GIT" GIT_REV #endif @@ -2472,11 +2472,17 @@ class cSoftHdDevice:public cDevice return "softhdcuvid"; } #endif -#ifdef VAAPI +#if defined (VAAPI) && !defined (USE_DRM) virtual cString DeviceName(void) const { return "softhdvaapi"; } +#endif +#if defined (VAAPI) && defined (USE_DRM) + virtual cString DeviceName(void) const + { + return "softhddrm"; + } #endif virtual bool HasDecoder(void) const; virtual bool CanReplay(void) const; diff --git a/video.c b/video.c index 2fcc453..8474ece 100644 --- a/video.c +++ b/video.c @@ -491,7 +491,7 @@ static void GlxSetupWindow(xcb_window_t window, int width, int height, GLXContex GLXContext OSDcontext; #else static EGLContext eglSharedContext; ///< shared gl context - +static EGLContext eglOSDContext = NULL; ///< our gl context for the thread static EGLContext eglContext; ///< our gl context static EGLConfig eglConfig; static EGLDisplay eglDisplay; @@ -501,6 +501,11 @@ static int eglVersion = 2; static EGLImageKHR(EGLAPIENTRY * CreateImageKHR) (EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, const EGLint *); static EGLBoolean(EGLAPIENTRY * DestroyImageKHR) (EGLDisplay, EGLImageKHR); static void (EGLAPIENTRY * EGLImageTargetTexture2DOES) (GLenum, GLeglImageOES); +PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR; +PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR; +PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR; +PFNEGLCLIENTWAITSYNCKHRPROC eglClientWaitSyncKHR; +PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID; #ifdef USE_VIDEO_THREAD static EGLContext eglThreadContext; ///< our gl context for the thread @@ -527,6 +532,14 @@ static void X11DPMSReenable(xcb_connection_t *); static void X11DPMSDisable(xcb_connection_t *); #endif +//---------------------------------------------------------------------------- +// DRM Helper Functions +//---------------------------------------------------------------------------- +#ifdef USE_DRM +#include "drm.c" +#include "hdr.c" +#endif + /// /// Update video pts. /// @@ -611,6 +624,7 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width, in input_aspect_ratio.num = 1; input_aspect_ratio.den = 1; Debug(3, "video: aspect defaults to %d:%d\n", input_aspect_ratio.num, input_aspect_ratio.den); + } av_reduce(&input_aspect_ratio.num, &input_aspect_ratio.den, input_width * input_aspect_ratio.num, @@ -621,10 +635,13 @@ static void VideoUpdateOutput(AVRational input_aspect_ratio, int input_width, in input_aspect_ratio.num = 1; input_aspect_ratio.den = 1; } - +#ifdef USE_DRM + display_aspect_ratio.num = 16;VideoWindowWidth; + display_aspect_ratio.den = 9; VideoWindowHeight; +#else 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 display_aspect_ratio = av_mul_q(input_aspect_ratio, display_aspect_ratio); Debug(3, "video: aspect %d:%d Resolution %d\n", display_aspect_ratio.num, display_aspect_ratio.den, resolution); @@ -843,27 +860,7 @@ char *eglErrorString(EGLint error) }\ } -#ifdef VAAPI -void OSD_get_shared_context() -{ - eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglSharedContext); - EglCheck(); -} - -void OSD_get_context() -{ - eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, OSDcontext); - EglCheck(); -} - -void OSD_release_context() -{ - eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - // EglCheck(); -} - -#endif /// /// GLX check if a GLX extension is supported. @@ -950,7 +947,7 @@ static void GlxSetupWindow(xcb_window_t window, int width, int height, EGLContex glViewport(0, 0, width, height); GlxCheck(); #ifdef VAAPI - OSD_release_context(); + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); #endif } @@ -1706,9 +1703,10 @@ static void CuvidPrintFrames(const CuvidDecoder * decoder) int CuvidTestSurfaces() { + int i=0; if (CuvidDecoders[0] != NULL) { - if (atomic_read(&CuvidDecoders[0]->SurfacesFilled) < VIDEO_SURFACES_MAX) - return 1; + if (i = atomic_read(&CuvidDecoders[0]->SurfacesFilled) < VIDEO_SURFACES_MAX-1) + return i; return 0; } else return 0; @@ -1749,12 +1747,13 @@ const int mpgl_preferred_gl_versions[] = { 0 }; -static bool create_context_cb(EGLDisplay display, int es_version, EGLContext * out_context, EGLConfig * out_config) +static bool create_context_cb(EGLDisplay display, int es_version, EGLContext * out_context, EGLConfig * out_config, int *bpp) { EGLenum api; EGLint rend, *attribs; const char *name; + switch (es_version) { case 0: @@ -1803,10 +1802,11 @@ static bool create_context_cb(EGLDisplay display, int es_version, EGLContext * o EGLint num_configs; attribs = attributes10; - + *bpp = 10; if (!eglChooseConfig(display, attributes10, NULL, 0, &num_configs)) { // try 10 Bit Debug(3, " 10 Bit egl Failed\n"); attribs = attributes8; + *bpp = 8; if (!eglChooseConfig(display, attributes8, NULL, 0, &num_configs)) { // try 8 Bit num_configs = 0; } @@ -1814,6 +1814,7 @@ static bool create_context_cb(EGLDisplay display, int es_version, EGLContext * o EglCheck(); Debug(3, " 10 Bit egl Failed\n"); attribs = attributes8; + *bpp = 8; if (!eglChooseConfig(display, attributes8, NULL, 0, &num_configs)) { // try 8 Bit num_configs = 0; } @@ -1873,34 +1874,41 @@ static bool create_context_cb(EGLDisplay display, int es_version, EGLContext * o make_egl() { - + int bpp; CreateImageKHR = (void *)eglGetProcAddress("eglCreateImageKHR"); DestroyImageKHR = (void *)eglGetProcAddress("eglDestroyImageKHR"); EGLImageTargetTexture2DOES = (void *)eglGetProcAddress("glEGLImageTargetTexture2DOES"); - - if (!CreateImageKHR || !DestroyImageKHR || !EGLImageTargetTexture2DOES) + eglCreateSyncKHR = (void *)eglGetProcAddress("eglCreateSyncKHR"); + eglDestroySyncKHR = (void *)eglGetProcAddress("eglDestroySyncKHR"); + eglWaitSyncKHR = (void *)eglGetProcAddress("eglWaitSyncKHR"); + eglClientWaitSyncKHR = (void *)eglGetProcAddress("eglClientWaitSyncKHR"); + eglDupNativeFenceFDANDROID = (void *)eglGetProcAddress("eglDupNativeFenceFDANDROID"); + + if (!CreateImageKHR || !DestroyImageKHR || !EGLImageTargetTexture2DOES || !eglCreateSyncKHR) Fatal(_("Can't get EGL Extentions\n")); - +#ifndef USE_DRM eglDisplay = eglGetDisplay(XlibDisplay); - +#endif if (!eglInitialize(eglDisplay, NULL, NULL)) { Fatal(_("Could not initialize EGL.\n")); } - if (!create_context_cb(eglDisplay, 0, &eglContext, &eglConfig)) { + if (!create_context_cb(eglDisplay, 0, &eglContext, &eglConfig, &bpp)) { Fatal(_("Could not create EGL Context\n")); } int vID, n; eglGetConfigAttrib(eglDisplay, eglConfig, EGL_NATIVE_VISUAL_ID, &vID); Debug(3, "chose visual 0x%x\n", vID); - +#ifdef USE_DRM + InitBo(bpp); +#else eglSurface = eglCreateWindowSurface(eglDisplay, eglConfig, (EGLNativeWindowType) VideoWindow, NULL); if (eglSurface == EGL_NO_SURFACE) { Fatal(_("Could not create EGL surface!\n")); } - +#endif if (!eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglContext)) { Fatal(_("Could not make context current!\n")); } @@ -2108,6 +2116,7 @@ static void CuvidExit(void) } } CuvidDecoderN = 0; + Debug(3, "CuvidExit\n"); } @@ -2215,7 +2224,7 @@ void createTextureDst(CuvidDecoder * decoder, int anz, unsigned int size_x, unsi // make planes for image pl = &decoder->pl_images[i].planes[n]; pl->components = n == 0 ? 1 : 2; - pl->shift_x = 0.0f; + pl->shift_x = 0.0f; pl->shift_y = 0.0f; if (n == 0) { pl->component_mapping[0] = PL_CHANNEL_Y; @@ -2223,6 +2232,7 @@ void createTextureDst(CuvidDecoder * decoder, int anz, unsigned int size_x, unsi pl->component_mapping[2] = -1; pl->component_mapping[3] = -1; } else { + pl->shift_x = -0.5f; // PL_CHROMA_LEFT pl->component_mapping[0] = PL_CHANNEL_U; pl->component_mapping[1] = PL_CHANNEL_V; pl->component_mapping[2] = -1; @@ -2347,7 +2357,7 @@ void generateVAAPIImage(CuvidDecoder * decoder, int index, const AVFrame * frame } #endif -#else +#else // no PLACEBO void createTextureDst(CuvidDecoder * decoder, int anz, unsigned int size_x, unsigned int size_y, enum AVPixelFormat PixFmt) @@ -2362,7 +2372,7 @@ void createTextureDst(CuvidDecoder * decoder, int anz, unsigned int size_x, unsi glXMakeCurrent(XlibDisplay, VideoWindow, glxSharedContext); GlxCheck(); #else - OSD_get_shared_context(); + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglSharedContext); #endif glGenBuffers(1, &vao_buffer); @@ -2402,7 +2412,7 @@ void createTextureDst(CuvidDecoder * decoder, int anz, unsigned int size_x, unsi glBindTexture(GL_TEXTURE_2D, 0); GlxCheck(); #ifdef VAAPI - OSD_release_context(); + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); #endif } @@ -2442,10 +2452,10 @@ void generateVAAPIImage(CuvidDecoder * decoder, int index, const AVFrame * frame return; } vaSyncSurface(decoder->VaDisplay, (unsigned int)frame->data[3]); - +//#ifndef USE_DRM eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglSharedContext); EglCheck(); - +//#endif for (int n = 0; n < 2; n++) { int attribs[20] = { EGL_NONE }; int num_attribs = 0; @@ -2456,8 +2466,8 @@ void generateVAAPIImage(CuvidDecoder * decoder, int index, const AVFrame * frame ADD_PLANE_ATTRIBS(0); decoder->images[index * 2 + n] = - CreateImageKHR(eglGetCurrentDisplay(), EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); - + CreateImageKHR(eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attribs); + if (!decoder->images[index * 2 + n]) goto esh_failed; @@ -2519,6 +2529,7 @@ static void CuvidSyncRenderFrame(CuvidDecoder * decoder, const AVCodecContext * int push_filters(AVCodecContext * dec_ctx, CuvidDecoder * decoder, AVFrame * frame) { + int ret, i = 0; AVFrame *filt_frame = av_frame_alloc(); @@ -2527,12 +2538,12 @@ int push_filters(AVCodecContext * dec_ctx, CuvidDecoder * decoder, AVFrame * fra av_log(NULL, AV_LOG_ERROR, "Error while feeding the filtergraph\n"); } - // printf("Interlaced %d tff %d\n",frame->interlaced_frame,frame->top_field_first); +// printf("Interlaced %d tff %d\n",frame->interlaced_frame,frame->top_field_first); /* pull filtered frames from the filtergraph */ - while ((ret = av_buffersink_get_frame(decoder->buffersink_ctx, filt_frame)) >= 0) { + while ((ret = av_buffersink_get_frame(decoder->buffersink_ctx, filt_frame)) >= 0 ) { filt_frame->pts /= 2; decoder->Interlaced = 0; - // printf("vaapideint video:new %#012" PRIx64 " old %#012" PRIx64 "\n",filt_frame->pts,frame->pts); +// printf("vaapideint video:new %#012" PRIx64 " old %#012" PRIx64 "\n",filt_frame->pts,frame->pts); CuvidSyncRenderFrame(decoder, dec_ctx, filt_frame); filt_frame = av_frame_alloc(); // get new frame @@ -2744,8 +2755,7 @@ static enum AVPixelFormat Cuvid_get_format(CuvidDecoder * decoder, AVCodecContex CuvidSetupOutput(decoder); #ifdef PLACEBO VideoThreadUnlock(); -#endif -#ifdef PLACEBO // dont show first frame + // dont show first frame decoder->newchannel = 1; #endif #ifdef YADIF @@ -3390,6 +3400,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) struct pl_color_adjustment colors; struct pl_cone_params cone; struct pl_tex_vk *vkp; + struct pl_plane *pl; const struct pl_fmt *fmt; VkImage Image; struct pl_image *img; @@ -3404,7 +3415,9 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) int y; float xcropf, ycropf; GLint texLoc; - + AVFrame *frame; + AVFrameSideData *FrameSideData = NULL; + #ifdef PLACEBO if (level) { dst_rect.x0 = decoder->VideoX; // video window output (clip) @@ -3433,9 +3446,14 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) ycropf = (float)decoder->CropY / (float)decoder->InputHeight; current = decoder->SurfacesRb[decoder->SurfaceRead]; - if (!decoder->Closing) { - VideoSetPts(&decoder->PTS, decoder->Interlaced, 0, decoder->frames[current]); + frame = decoder->frames[current]; + VideoSetPts(&decoder->PTS, decoder->Interlaced, 0, frame); +#ifdef USE_DRM + AVFrameSideData *sd1 = av_frame_get_side_data (frame, AV_FRAME_DATA_MASTERING_DISPLAY_METADATA); + AVFrameSideData *sd2 = av_frame_get_side_data (frame, AV_FRAME_DATA_CONTENT_LIGHT_LEVEL); + set_hdr_metadata(frame->color_primaries,frame->color_trc,sd1,sd2); +#endif } // Render Progressive frame @@ -3466,7 +3484,8 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) #else img = &decoder->pl_images[current]; - + pl = &decoder->pl_images[current].planes[1]; + memcpy(&deband, &pl_deband_default_params, sizeof(deband)); memcpy(&render_params, &pl_render_default_params, sizeof(render_params)); @@ -3476,6 +3495,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) img->color.primaries = PL_COLOR_PRIM_BT_601_625; img->color.transfer = PL_COLOR_TRC_BT_1886; img->color.light = PL_COLOR_LIGHT_DISPLAY; + pl->shift_x = 0.0f; break; case AVCOL_SPC_BT709: case AVCOL_SPC_UNSPECIFIED: // comes with UHD @@ -3485,6 +3505,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) // img->color.transfer = PL_COLOR_TRC_BT_1886; // img->color.light = PL_COLOR_LIGHT_SCENE_709_1886; // img->color.light = PL_COLOR_LIGHT_DISPLAY; + pl->shift_x = -0.5f; break; case AVCOL_SPC_BT2020_NCL: @@ -3492,7 +3513,8 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) memcpy(&img->repr, &pl_color_repr_uhdtv, sizeof(struct pl_color_repr)); memcpy(&img->color, &pl_color_space_bt2020_hlg, sizeof(struct pl_color_space)); deband.grain = 0.0f; // no grain in HDR - img->color.sig_scale = 2.0f; + img->color.sig_scale = 1.0f; + pl->shift_x = -0.5f; #ifdef VAAPI render_params.peak_detect_params = NULL; #endif @@ -3507,6 +3529,7 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused)) // img->color.primaries = PL_COLOR_PRIM_BT_709; // img->color.transfer = PL_COLOR_TRC_BT_1886; // img->color.light = PL_COLOR_LIGHT_DISPLAY; + pl->shift_x = -0.5f; break; } // Source crop @@ -3696,20 +3719,23 @@ static void CuvidDisplayFrame(void) int RTS_flag; int valid_frame = 0; float ldiff; - + static int first = 1; + float turnaround; + #ifdef PLACEBO uint64_t diff; static float fdiff = 23000.0; struct pl_swapchain_frame frame; struct pl_render_target target; bool ok; - static int first = 1; + VkImage Image; const struct pl_fmt *fmt; const float black[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; #endif #ifndef PLACEBO + if (CuvidDecoderN) CuvidDecoders[0]->Frameproc = (float)(GetusTicks() - last_time) / 1000000.0; @@ -3723,7 +3749,7 @@ static void CuvidDisplayFrame(void) #endif glClear(GL_COLOR_BUFFER_BIT); -#else +#else // PLACEBO if (CuvidDecoderN) { ldiff = (float)(GetusTicks() - round_time) / 1000000.0; @@ -3826,7 +3852,7 @@ static void CuvidDisplayFrame(void) decoder->StartCounter++; filled = atomic_read(&decoder->SurfacesFilled); - +//printf("Filled %d\n",filled); // need 1 frame for progressive, 3 frames for interlaced if (filled < 1 + 2 * decoder->Interlaced) { // FIXME: rewrite MixVideo to support less surfaces @@ -3882,6 +3908,8 @@ static void CuvidDisplayFrame(void) int x, y, w, h; glBindTexture(GL_TEXTURE_2D, 0); + GlxCheck(); + if (OsdShown == 1) { if (OSDtexture) glDeleteTextures(1, &OSDtexture); @@ -3889,15 +3917,19 @@ static void CuvidDisplayFrame(void) glGenTextures(1, &OSDtexture); glBindTexture(GL_TEXTURE_2D, OSDtexture); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, OSDxsize, OSDysize, 0, GL_RGBA, GL_UNSIGNED_BYTE, posd); + GlxCheck(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + GlxCheck(); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); glFlush(); pthread_mutex_unlock(&OSDMutex); OsdShown = 2; } + GlxCheck(); glBindTexture(GL_TEXTURE_2D, 0); + GlxCheck(); glEnable(GL_BLEND); GlxCheck(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -3925,6 +3957,7 @@ static void CuvidDisplayFrame(void) glUseProgram(0); glActiveTexture(GL_TEXTURE0); + eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglThreadContext); } #endif @@ -3938,14 +3971,18 @@ static void CuvidDisplayFrame(void) #endif VideoThreadUnlock(); -#else +#else // not PLACEBO #ifdef CUVID glXGetVideoSyncSGI(&Count); // get current frame glXSwapBuffers(XlibDisplay, VideoWindow); glXMakeCurrent(XlibDisplay, None, NULL); #else +#ifndef USE_DRM eglSwapBuffers(eglDisplay, eglSurface); eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +#else + drm_swap_buffers(); +#endif #endif #endif @@ -4326,9 +4363,7 @@ static void CuvidDisplayHandlerThread(void) allfull = 1; decoded = 0; -#ifndef PLACEBO - VideoThreadLock(); -#endif + for (i = 0; i < CuvidDecoderN; ++i) { decoder = CuvidDecoders[i]; @@ -4343,9 +4378,9 @@ static void CuvidDisplayHandlerThread(void) allfull = 0; err = VideoDecodeInput(decoder->Stream); } else { -#ifdef PLACEBO + usleep(1000); -#endif + err = VideoPollInput(decoder->Stream); } // decoder can be invalid here @@ -4358,26 +4393,24 @@ static void CuvidDisplayHandlerThread(void) decoder->Closing = -1; } } -#ifdef PLACEBO + usleep(1000); -#endif + continue; } decoded = 1; } -#ifndef PLACEBO - VideoThreadUnlock(); -#endif + if (!decoded) { // nothing decoded, sleep // FIXME: sleep on wakeup usleep(1 * 1000); } -#ifdef PLACEBO + usleep(1000); -#endif + // all decoder buffers are full // and display is not preempted @@ -4390,11 +4423,6 @@ static void CuvidDisplayHandlerThread(void) return; } } -#ifndef PLACEBO - VideoThreadLock(); - CuvidSyncDisplayFrame(); - VideoThreadUnlock(); -#endif return; } @@ -5103,15 +5131,15 @@ static void *VideoDisplayHandlerThread(void *dummy) glxThreadContext = glXCreateContext(XlibDisplay, GlxVisualInfo, glxSharedContext, GL_TRUE); GlxSetupWindow(VideoWindow, VideoWindowWidth, VideoWindowHeight, glxThreadContext); #else +#if 0 eglThreadContext = eglCreateContext(eglDisplay, eglConfig, eglSharedContext, contextAttrs); - if (!eglThreadContext) { EglCheck(); Fatal(_("video/egl: can't create thread egl context\n")); return NULL; } #endif - +#endif } sleep(2); for (;;) { @@ -5119,26 +5147,34 @@ static void *VideoDisplayHandlerThread(void *dummy) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_testcancel(); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); -#ifndef PLACEBO - VideoPollEvent(); -#endif + VideoUsedModule->DisplayHandlerThread(); } return dummy; } -#ifdef PLACEBO + static void *VideoHandlerThread(void *dummy) { - - uint64_t first_time; - + EGLint contextAttrs[] = { + EGL_CONTEXT_CLIENT_VERSION, 3, + EGL_NONE + }; prctl(PR_SET_NAME, "cuvid video display", 0, 0, 0); - +#ifdef PLACEBO InitPlacebo(); - pthread_cleanup_push(delete_placebo, NULL); + +#else + eglThreadContext = eglCreateContext(eglDisplay, eglConfig, eglSharedContext, contextAttrs); + if (!eglThreadContext) { + EglCheck(); + Fatal(_("video/egl: can't create thread egl context\n")); + return NULL; + } + eglMakeCurrent(eglDisplay, eglSurface, eglSurface, eglThreadContext); +#endif for (;;) { pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); @@ -5149,15 +5185,14 @@ static void *VideoHandlerThread(void *dummy) // first_time = GetusTicks(); CuvidSyncDisplayFrame(); - // printf("syncdisplayframe exec %d\n",(GetusTicks()-first_time)/1000); } - +#ifdef PLACEBO pthread_cleanup_pop(NULL); - +#endif return dummy; } -#endif + /// /// Initialize video threads. /// @@ -5176,12 +5211,9 @@ static void VideoThreadInit(void) pthread_mutex_init(&OSDMutex, NULL); pthread_cond_init(&VideoWakeupCond, NULL); pthread_create(&VideoThread, NULL, VideoDisplayHandlerThread, NULL); -#ifdef PLACEBO + pthread_create(&VideoDisplayThread, NULL, VideoHandlerThread, NULL); -#else - VideoDisplayThread = 0; -#endif } /// @@ -5241,9 +5273,11 @@ static void VideoThreadExit(void) /// void VideoDisplayWakeup(void) { +#ifndef USE_DRM if (!XlibDisplay) { // not yet started return; } +#endif if (!VideoThread) { // start video thread, if needed VideoThreadInit(); @@ -6444,6 +6478,10 @@ void VideoInit(const char *display_name) xcb_screen_iterator_t screen_iter; xcb_screen_t const *screen; +#ifdef USE_DRM + VideoInitDrm(); +#else + if (XlibDisplay) { // allow multiple calls Debug(3, "video: x11 already setup\n"); return; @@ -6526,7 +6564,7 @@ void VideoInit(const char *display_name) VideoCreateWindow(screen->root, screen->root_visual, screen->root_depth); Debug(3, "video: window prepared\n"); - +#endif // // prepare hardware decoder // @@ -6545,6 +6583,8 @@ void VideoInit(const char *display_name) VideoUsedModule = &NoopModule; found: + ; +#ifndef USE_DRM // FIXME: make it configurable from gui if (getenv("NO_MPEG_HW")) { VideoHardwareDecoder = 1; @@ -6558,7 +6598,7 @@ void VideoInit(const char *display_name) //xcb_prefetch_maximum_request_length(Connection); xcb_flush(Connection); - +#endif #ifdef PLACEBO_ InitPlacebo(); #endif @@ -6570,6 +6610,7 @@ void VideoInit(const char *display_name) /// void VideoExit(void) { +#ifndef USE_DRM if (!XlibDisplay) { // no init or failed return; } @@ -6578,7 +6619,7 @@ void VideoExit(void) // X11DPMSReenable(Connection); X11SuspendScreenSaver(Connection, 0); - +#endif VideoUsedModule->Exit(); VideoUsedModule = &NoopModule; @@ -6591,7 +6632,7 @@ void VideoExit(void) EglExit(); // delete all contexts } #endif - +#ifndef USE_DRM // // FIXME: cleanup. // @@ -6624,43 +6665,34 @@ void VideoExit(void) XlibDisplay = NULL; Connection = 0; } +#endif +#ifdef USE_DRM + drm_clean_up(); +#endif } -int GlxInitopengl() -{ -#ifndef PLACEBO -#ifdef VAAPI +#ifdef USE_DRM +int GlxInitopengl () { EGLint contextAttrs[] = { EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE }; - while (eglSharedContext == NULL || eglContext == NULL) { - sleep(1); // wait until Init from video thread is ready + if (!eglOSDContext) { + eglOSDContext = eglCreateContext(eglDisplay, eglConfig, eglSharedContext, contextAttrs); + if (!eglOSDContext) { + EglCheck(); + Fatal(_("video/egl: can't create thread egl context\n")); + return NULL; + } } -#endif -#ifdef CUVID - while (glxSharedContext == NULL || glxContext == NULL) { - sleep(1); // wait until Init from video thread is ready - } - OSDcontext = glXCreateContext(XlibDisplay, GlxVisualInfo, glxSharedContext, GL_TRUE); -#else - OSDcontext = eglCreateContext(eglDisplay, eglConfig, eglSharedContext, contextAttrs); -#endif - if (!OSDcontext) { - Debug(3, "video/osd: can't create OSD egl context\n"); - return 0; - } - Debug(3, "Create OSD egl context\n"); -#ifdef VAAPI -// eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, OSDcontext); -// EglCheck(); -#else - glXMakeCurrent(XlibDisplay, VideoWindow, OSDcontext); - GlxCheck(); -#endif - -#endif - return 1; - + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglOSDContext); + return; } + +int GlxDrawopengl () { + eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglSharedContext); + return; +} +#endif +