mirror of
https://github.com/jojo61/vdr-plugin-softhdcuvid.git
synced 2023-10-10 13:37:41 +02:00
Inital Support for DRM with HDR10 and HDR-HLG
This commit is contained in:
parent
f17e58c7c5
commit
3bed988b14
31
Makefile
31
Makefile
@ -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
|
||||
@ -152,6 +159,14 @@ 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
|
||||
@ -261,7 +276,7 @@ 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
|
||||
-g -W -Wextra -Winit-self -Werror=overloaded-virtual -Wno-unused-parameter
|
||||
override CFLAGS += $(_CFLAGS) $(DEFINES) $(INCLUDES) \
|
||||
-g -W -Wextra -Winit-self -Wdeclaration-after-statement
|
||||
|
||||
@ -273,7 +288,7 @@ ifeq ($(OPENGLOSD),1)
|
||||
OBJS += openglosd.o
|
||||
endif
|
||||
|
||||
SRCS = $(wildcard $(OBJS:.o=.c)) softhdcuvid.cpp
|
||||
SRCS = $(wildcard $(OBJS:.o=.c)) *.cpp
|
||||
|
||||
### The main target:
|
||||
|
||||
@ -348,6 +363,8 @@ 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
|
||||
|
471
drm.c
Normal file
471
drm.c
Normal file
@ -0,0 +1,471 @@
|
||||
#include <unistd.h>
|
||||
#include <gbm.h>
|
||||
#include <sys/mman.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
||||
#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);
|
||||
}
|
491
hdr.c
Normal file
491
hdr.c
Normal file
@ -0,0 +1,491 @@
|
||||
#include <libavutil/mastering_display_metadata.h>
|
||||
|
||||
/**
|
||||
* 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");
|
||||
|
||||
}
|
||||
|
@ -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
|
||||
****************************************************************************************/
|
||||
@ -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,6 +1750,7 @@ bool cOglThread::InitOpenGL(void) {
|
||||
esyslog("[softhddev]glewInit failed, aborting\n");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
VertexBuffers[vbText]->EnableBlending();
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
@ -1790,8 +1813,9 @@ void cOglThread::Cleanup(void) {
|
||||
DeleteShaders();
|
||||
// glVDPAUFiniNV();
|
||||
cOglFont::Cleanup();
|
||||
#ifndef USE_DRM
|
||||
glutExit();
|
||||
|
||||
#endif
|
||||
pthread_mutex_unlock(&OSDMutex);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
270
video.c
270
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,13 +1747,14 @@ 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:
|
||||
api = EGL_OPENGL_API;
|
||||
@ -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");
|
||||
eglCreateSyncKHR = (void *)eglGetProcAddress("eglCreateSyncKHR");
|
||||
eglDestroySyncKHR = (void *)eglGetProcAddress("eglDestroySyncKHR");
|
||||
eglWaitSyncKHR = (void *)eglGetProcAddress("eglWaitSyncKHR");
|
||||
eglClientWaitSyncKHR = (void *)eglGetProcAddress("eglClientWaitSyncKHR");
|
||||
eglDupNativeFenceFDANDROID = (void *)eglGetProcAddress("eglDupNativeFenceFDANDROID");
|
||||
|
||||
if (!CreateImageKHR || !DestroyImageKHR || !EGLImageTargetTexture2DOES)
|
||||
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");
|
||||
|
||||
}
|
||||
@ -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,7 +2466,7 @@ 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();
|
||||
|
||||
@ -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,6 +3415,8 @@ static void CuvidMixVideo(CuvidDecoder * decoder, __attribute__((unused))
|
||||
int y;
|
||||
float xcropf, ycropf;
|
||||
GLint texLoc;
|
||||
AVFrame *frame;
|
||||
AVFrameSideData *FrameSideData = NULL;
|
||||
|
||||
#ifdef PLACEBO
|
||||
if (level) {
|
||||
@ -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,6 +3484,7 @@ 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,6 +3719,8 @@ static void CuvidDisplayFrame(void)
|
||||
int RTS_flag;
|
||||
int valid_frame = 0;
|
||||
float ldiff;
|
||||
static int first = 1;
|
||||
float turnaround;
|
||||
|
||||
#ifdef PLACEBO
|
||||
uint64_t diff;
|
||||
@ -3703,13 +3728,14 @@ static void CuvidDisplayFrame(void)
|
||||
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
|
||||
pthread_create(&VideoDisplayThread, NULL, VideoHandlerThread, NULL);
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
@ -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;
|
||||
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglOSDContext);
|
||||
return;
|
||||
}
|
||||
|
||||
int GlxDrawopengl () {
|
||||
eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, eglSharedContext);
|
||||
return;
|
||||
}
|
||||
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;
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user