Skip to content

Commit

Permalink
VideoPlayer: OpenGL - implement tone mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
FernetMenta committed Feb 10, 2018
1 parent 8f33367 commit 787a0c2
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 64 deletions.
8 changes: 2 additions & 6 deletions system/shaders/GL/1.2/gl_yuv2rgb_basic.glsl
Expand Up @@ -122,13 +122,9 @@ vec4 process()
#endif

#if defined(XBMC_COL_CONVERSION)
rgb.r = pow(rgb.r, m_gammaSrc);
rgb.g = pow(rgb.g, m_gammaSrc);
rgb.b = pow(rgb.b, m_gammaSrc);
rgb.rgb = pow(rgb.rgb, vec3(m_gammaSrc));
rgb.rgb = m_primMat * rgb.rgb;
rgb.r = pow(rgb.r, m_gammaDstInv);
rgb.g = pow(rgb.g, m_gammaDstInv);
rgb.b = pow(rgb.b, m_gammaDstInv);
rgb.rgb = pow(rgb.rgb, vec3(m_gammaDstInv));
#endif

return rgb;
Expand Down
4 changes: 4 additions & 0 deletions system/shaders/GL/1.5/gl_tonemap.glsl
@@ -0,0 +1,4 @@
float tonemap(float val)
{
return val * (1 + val/(m_toneP1*m_toneP1))/(1 + val);
}
37 changes: 20 additions & 17 deletions system/shaders/GL/1.5/gl_yuv2rgb_basic.glsl
Expand Up @@ -15,6 +15,8 @@ uniform float m_alpha;
uniform mat3 m_primMat;
uniform float m_gammaDstInv;
uniform float m_gammaSrc;
uniform float m_toneP1;
uniform vec3 m_coefsDst;
in vec2 m_cordY;
in vec2 m_cordU;
in vec2 m_cordV;
Expand All @@ -41,25 +43,20 @@ vec2 stretch(vec2 pos)
vec4 process()
{
vec4 rgb;
vec4 yuv;

#if defined(XBMC_YV12)

vec4 yuv;
yuv.rgba = vec4( texture(m_sampY, stretch(m_cordY)).r
, texture(m_sampU, stretch(m_cordU)).r
, texture(m_sampV, stretch(m_cordV)).r
, 1.0 );

rgb = m_yuvmat * yuv;
rgb.a = m_alpha;

#elif defined(XBMC_NV12)

vec4 yuv;
yuv.rgba = vec4( texture(m_sampY, stretch(m_cordY)).r
, texture(m_sampU, stretch(m_cordU)).rg
, 1.0 );
rgb = m_yuvmat * yuv;
rgb.a = m_alpha;

#elif defined(XBMC_YUY2) || defined(XBMC_UYVY)

Expand All @@ -86,23 +83,29 @@ vec4 process()
vec2 outUV = mix(c1.br, c2.br, f.x);
#endif //XBMC_YUY2

float outY = mix(leftY, rightY, step(0.5, f.x));
float outY = mix(leftY, rightY, step(0.5, f.x));

vec4 yuv = vec4(outY, outUV, 1.0);
rgb = m_yuvmat * yuv;
yuv = vec4(outY, outUV, 1.0);

rgb.a = m_alpha;
#endif

#if defined(XBMC_TONE_MAPPING)
//float scale = tonemap(yuv.x) / yuv.x;
#endif

rgb = m_yuvmat * yuv;
rgb.a = m_alpha;

#if defined(XBMC_COL_CONVERSION)
rgb.r = pow(rgb.r, m_gammaSrc);
rgb.g = pow(rgb.g, m_gammaSrc);
rgb.b = pow(rgb.b, m_gammaSrc);
rgb.rgb = pow(rgb.rgb, vec3(m_gammaSrc));
rgb.rgb = m_primMat * rgb.rgb;
rgb.r = pow(rgb.r, m_gammaDstInv);
rgb.g = pow(rgb.g, m_gammaDstInv);
rgb.b = pow(rgb.b, m_gammaDstInv);
rgb.rgb = pow(rgb.rgb, vec3(m_gammaDstInv));

#if defined(XBMC_TONE_MAPPING)
float luma = dot(rgb.rgb, m_coefsDst);
rgb.rgb *= tonemap(luma) / luma;
#endif

#endif

return rgb;
Expand Down
40 changes: 23 additions & 17 deletions system/shaders/GL/4.0/gl_yuv2rgb_filter4.glsl
Expand Up @@ -16,6 +16,8 @@ uniform sampler1D m_kernelTex;
uniform mat3 m_primMat;
uniform float m_gammaDstInv;
uniform float m_gammaSrc;
uniform float m_toneP1;
uniform vec3 m_coefsDst;
in vec2 m_cordY;
in vec2 m_cordU;
in vec2 m_cordV;
Expand Down Expand Up @@ -88,33 +90,37 @@ float filter_0(sampler2D sampler, vec2 coord)
vec4 process()
{
vec4 rgb;
#if defined(XBMC_YV12)
vec4 yuv;

vec4 yuv = vec4(filter_0(m_sampY, stretch(m_cordY)),
texture(m_sampU, stretch(m_cordU)).r,
texture(m_sampV, stretch(m_cordV)).r,
1.0);
#if defined(XBMC_YV12)

rgb = m_yuvmat * yuv;
rgb.a = m_alpha;
yuv = vec4(filter_0(m_sampY, stretch(m_cordY)),
texture(m_sampU, stretch(m_cordU)).r,
texture(m_sampV, stretch(m_cordV)).r,
1.0);

#elif defined(XBMC_NV12)

vec4 yuv = vec4(filter_0(m_sampY, stretch(m_cordY)),
texture(m_sampU, stretch(m_cordU)).rg,
1.0);
yuv = vec4(filter_0(m_sampY, stretch(m_cordY)),
texture(m_sampU, stretch(m_cordU)).rg,
1.0);

#endif

rgb = m_yuvmat * yuv;
rgb.a = m_alpha;
#endif

#if defined(XBMC_COL_CONVERSION)
rgb.r = pow(rgb.r, m_gammaSrc);
rgb.g = pow(rgb.g, m_gammaSrc);
rgb.b = pow(rgb.b, m_gammaSrc);
rgb.rgb = pow(rgb.rgb, vec3(m_gammaSrc));
rgb.rgb = m_primMat * rgb.rgb;
rgb.r = pow(rgb.r, m_gammaDstInv);
rgb.g = pow(rgb.g, m_gammaDstInv);
rgb.b = pow(rgb.b, m_gammaDstInv);
rgb.rgb = pow(rgb.rgb, vec3(m_gammaDstInv));

#if defined(XBMC_TONE_MAPPING)
float luma = dot(rgb.rgb, m_coefsDst);
rgb.rgb *= tonemap(luma) / luma;
#endif

#endif

return rgb;
}
25 changes: 24 additions & 1 deletion xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp
Expand Up @@ -252,6 +252,7 @@ bool CLinuxRendererGL::Configure(const VideoPicture &picture, float fps, unsigne

m_srcPrimaries = GetSrcPrimaries(static_cast<AVColorPrimaries>(picture.color_primaries),
picture.iWidth, picture.iHeight);
m_toneMap = false;

// Calculate the input frame aspect ratio.
CalculateFrameAspectRatio(picture.iDisplayWidth, picture.iDisplayHeight);
Expand Down Expand Up @@ -324,6 +325,11 @@ void CLinuxRendererGL::AddVideoPicture(const VideoPicture &picture, int index, d
buf.m_srcColSpace = static_cast<AVColorSpace>(picture.color_space);
buf.m_srcFullRange = picture.color_range == 1;
buf.m_srcBits = picture.colorBits;

buf.hasDisplayMetadata = picture.hasDisplayMetadata;
buf.displayMetadata = picture.displayMetadata;
buf.hasLightMetadata = picture.hasLightMetadata;
buf.lightMetadata = picture.lightMetadata;
}

void CLinuxRendererGL::ReleaseBuffer(int idx)
Expand Down Expand Up @@ -916,6 +922,7 @@ void CLinuxRendererGL::LoadShaders(int field)
m_pYUVShader = new YUV2RGBFilterShader4(m_textureTarget == GL_TEXTURE_RECTANGLE_ARB,
shaderFormat, m_nonLinStretch,
AVColorPrimaries::AVCOL_PRI_BT709, m_srcPrimaries,
m_toneMap,
m_scalingMethod, out);
if (!m_cmsOn)
m_pYUVShader->SetConvertFullColorRange(m_fullRange);
Expand All @@ -940,7 +947,7 @@ void CLinuxRendererGL::LoadShaders(int field)
{
m_pYUVShader = new YUV2RGBProgressiveShader(m_textureTarget == GL_TEXTURE_RECTANGLE_ARB, shaderFormat,
m_nonLinStretch && m_renderQuality == RQ_SINGLEPASS,
AVColorPrimaries::AVCOL_PRI_BT709, m_srcPrimaries, out);
AVColorPrimaries::AVCOL_PRI_BT709, m_srcPrimaries, m_toneMap, out);

if (!m_cmsOn)
m_pYUVShader->SetConvertFullColorRange(m_fullRange);
Expand Down Expand Up @@ -1062,6 +1069,13 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field)
m_reloadShaders = true;
}

bool toneMap = false;
if (buf.hasLightMetadata || (buf.hasDisplayMetadata && buf.displayMetadata.has_luminance))
toneMap = true;
if (toneMap != m_toneMap)
m_reloadShaders = true;
m_toneMap = toneMap;

if (m_reloadShaders)
{
LoadShaders(field);
Expand Down Expand Up @@ -1089,6 +1103,8 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field)
m_pYUVShader->SetWidth(planes[0].texwidth);
m_pYUVShader->SetHeight(planes[0].texheight);
m_pYUVShader->SetColParams(buf.m_srcColSpace, buf.m_srcBits, !buf.m_srcFullRange, buf.m_srcTextureBits);
m_pYUVShader->SetDisplayMetadata(buf.hasDisplayMetadata, buf.displayMetadata,
buf.hasLightMetadata, buf.lightMetadata);

//disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer
//having non-linear stretch on breaks the alignment
Expand Down Expand Up @@ -1214,6 +1230,13 @@ void CLinuxRendererGL::RenderToFBO(int index, int field, bool weave /*= false*/)
m_reloadShaders = true;
}

bool toneMap = false;
if (buf.hasLightMetadata || (buf.hasDisplayMetadata && buf.displayMetadata.has_luminance))
toneMap = true;
if (toneMap != m_toneMap)
m_reloadShaders = true;
m_toneMap = toneMap;

if (m_reloadShaders)
{
m_reloadShaders = 0;
Expand Down
31 changes: 10 additions & 21 deletions xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h
Expand Up @@ -37,6 +37,10 @@
#include "threads/Event.h"
#include "VideoShaders/ShaderFormats.h"

extern "C" {
#include "libavutil/mastering_display_metadata.h"
}

class CRenderCapture;
class CRenderSystemGL;

Expand All @@ -52,20 +56,6 @@ struct DRAWRECT
float bottom;
};

struct YUVRANGE
{
int y_min, y_max;
int u_min, u_max;
int v_min, v_max;
};

struct YUVCOEF
{
float r_up, r_vp;
float g_up, g_vp;
float b_up, b_vp;
};

enum RenderMethod
{
RENDER_GLSL=0x01,
Expand All @@ -87,13 +77,6 @@ enum RenderQuality
#define FIELD_TOP 1
#define FIELD_BOT 2

extern YUVRANGE yuv_range_lim;
extern YUVRANGE yuv_range_full;
extern YUVCOEF yuv_coef_bt601;
extern YUVCOEF yuv_coef_bt709;
extern YUVCOEF yuv_coef_ebu;
extern YUVCOEF yuv_coef_smtp240m;

class CLinuxRendererGL : public CBaseRenderer
{
public:
Expand Down Expand Up @@ -220,6 +203,11 @@ class CLinuxRendererGL : public CBaseRenderer
int m_srcBits = 8;
int m_srcTextureBits = 8;
bool m_srcFullRange;

bool hasDisplayMetadata = false;
AVMasteringDisplayMetadata displayMetadata;
bool hasLightMetadata = false;
AVContentLightMetadata lightMetadata;
};

// YV12 decoder textures
Expand All @@ -240,6 +228,7 @@ class CLinuxRendererGL : public CBaseRenderer
unsigned int m_ditherDepth;
bool m_fullRange;
AVColorPrimaries m_srcPrimaries;
bool m_toneMap = false;

// clear colour for "black" bars
float m_clearColour;
Expand Down
Expand Up @@ -562,3 +562,35 @@ float CConvertMatrix::GetGammaDst()
{
return m_gammaDst;
}

bool CConvertMatrix::GetRGBYuvCoefs(AVColorSpace colspace, float (&coefs)[3])
{
switch (colspace)
{
case AVCOL_SPC_BT709:
coefs[0] = BT709YCbCr.Kr;
coefs[1] = 1 - BT709YCbCr.Kr - BT709YCbCr.Kb;
coefs[2] = BT709YCbCr.Kb;
break;
case AVCOL_SPC_BT470BG:
case AVCOL_SPC_SMPTE170M:
coefs[0] = BT601YCbCr.Kr;
coefs[1] = 1 - BT601YCbCr.Kr - BT601YCbCr.Kb;
coefs[2] = BT601YCbCr.Kb;
break;
case AVCOL_SPC_SMPTE240M:
coefs[0] = ST240YCbCr.Kr;
coefs[1] = 1 - ST240YCbCr.Kr - ST240YCbCr.Kb;
coefs[2] = ST240YCbCr.Kb;
break;
case AVCOL_SPC_BT2020_NCL:
case AVCOL_SPC_BT2020_CL:
coefs[0] = ST240YCbCr.Kr;
coefs[1] = 1 - ST240YCbCr.Kr - ST240YCbCr.Kb;
coefs[2] = ST240YCbCr.Kb;
break;
default:
return false;
}
return true;
}
Expand Up @@ -123,6 +123,7 @@ class CConvertMatrix
bool GetPrimMat(float (&mat)[3][3]);
float GetGammaSrc();
float GetGammaDst();
bool GetRGBYuvCoefs(AVColorSpace colspace, float (&coefs)[3]);

protected:
void GenMat();
Expand Down

0 comments on commit 787a0c2

Please sign in to comment.