Skip to content

Commit

Permalink
VideoColourSpace: Pass the colourspace from FFmpeg to the player
Browse files Browse the repository at this point in the history
- create new colourspace defines in VideoFrame
- translate FFmpeg colorspaces that we support and pass on through the
video buffers
- check colourspace at the start of each frame presentation in
VideoOutput classes (as before - only OpenGL and VDPAU support
colourspaces).
- add an RGBA colorspace that will be used in the near future
- the UHD/rec 2020 colourspace hasn't been added as I can't find any
material that explicitly reports it is using it. I suspect we just need
to assume any 10bit pixel format is using a 10bit colorspace.

Refs #13376
  • Loading branch information
mark-kendall committed Jan 25, 2019
1 parent c48979b commit 1d39f1a
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 23 deletions.
20 changes: 20 additions & 0 deletions mythtv/libs/libmythtv/avformatdecoder.cpp
Expand Up @@ -404,6 +404,25 @@ void AvFormatDecoder::GetDecoders(render_opts &opts)
PrivateDecoder::GetDecoders(opts);
}

/*! \brief Translate AVColorSpace to supported MythTV colorspaces.
* This currently makes no attempt to guess when the colorspace is undefined.
*/
static inline MythColorSpace GetColorSpace(AVFrame *Frame)
{
switch (Frame->colorspace)
{
case AVCOL_SPC_RGB: return ColorSpaceRGB;
case AVCOL_SPC_BT709: return ColorSpaceBT709;
case AVCOL_SPC_SMPTE240M: return ColorSpaceSMPTE240M;
case AVCOL_SPC_BT2020_NCL:
case AVCOL_SPC_BT2020_CL: return ColorSpaceBT2020;
case AVCOL_SPC_BT470BG:
case AVCOL_SPC_SMPTE170M: return ColorSpaceBT601;
default: break;
}
return ColorSpaceUnknown;
}

AvFormatDecoder::AvFormatDecoder(MythPlayer *parent,
const ProgramInfo &pginfo,
PlayerFlags flags)
Expand Down Expand Up @@ -4120,6 +4139,7 @@ bool AvFormatDecoder::ProcessVideoFrame(AVStream *stream, AVFrame *mpa_pic)
picframe->aspect = current_aspect;
picframe->dummy = 0;
picframe->directrendering = directrendering ? 1 : 0;
picframe->colorspace = GetColorSpace(mpa_pic);

m_parent->ReleaseNextVideoFrame(picframe, temppts);
}
Expand Down
11 changes: 11 additions & 0 deletions mythtv/libs/libmythtv/mythframe.h
Expand Up @@ -33,6 +33,16 @@ typedef enum FrameType_
FMT_NV12
} VideoFrameType;

typedef enum MythColorSpace_
{
ColorSpaceUnknown = 0,
ColorSpaceBT601,
ColorSpaceRGB,
ColorSpaceBT709,
ColorSpaceSMPTE240M,
ColorSpaceBT2020
} MythColorSpace;

typedef struct VideoFrame_
{
VideoFrameType codec;
Expand Down Expand Up @@ -65,6 +75,7 @@ typedef struct VideoFrame_

int pix_fmt;
int directrendering; ///< 1 if managed by FFmpeg
MythColorSpace colorspace;
} VideoFrame;

#ifdef __cplusplus
Expand Down
35 changes: 30 additions & 5 deletions mythtv/libs/libmythtv/videocolourspace.cpp
Expand Up @@ -5,7 +5,21 @@

#define LOC QString("ColourSpace: ")

VideoColourSpace::VideoColourSpace(VideoCStd colour_std)
static QString ToString(MythColorSpace ColorSpace)
{
switch (ColorSpace)
{
case ColorSpaceBT601: return "BT-601";
case ColorSpaceBT709: return "BT-709";
case ColorSpaceBT2020: return "BT-2020";
case ColorSpaceRGB: return "RGB";
case ColorSpaceSMPTE240M: return "SMPTE-240M";
default: break;
}
return "Unknown";
}

VideoColourSpace::VideoColourSpace(MythColorSpace colour_std)
: QMatrix4x4(),
m_supported_attributes(kPictureAttributeSupported_None),
m_changed(false),
Expand Down Expand Up @@ -111,23 +125,30 @@ void VideoColourSpace::Update(void)
QMatrix4x4 csc;
switch (m_colourSpace)
{
case kCSTD_SMPTE_240M:
case ColorSpaceRGB:
csc = QMatrix4x4(1.000f, 0.000f, 0.000f, 0.000f,
0.000f, 1.000f, 0.000f, 0.000f,
0.000f, 0.000f, 1.000f, 0.000f,
0.000f, 0.000f, 0.000f, m_alpha);
break;

case ColorSpaceSMPTE240M:
csc = QMatrix4x4(
1.000f, ( 1.5756f * uvsin), ( 1.5756f * uvcos) , 0.000f,
1.000f, (-0.2253f * uvcos) + ( 0.5000f * uvsin), ( 0.5000f * uvcos) - (-0.2253f * uvsin), 0.000f,
1.000f, ( 1.8270f * uvcos) , - ( 1.8270f * uvsin), 0.000f,
0.000f, 0.000f, 0.000f, m_alpha);
break;

case kCSTD_ITUR_BT_709:
case ColorSpaceBT709:
csc = QMatrix4x4(
1.000f, ( 1.5701f * uvsin), ( 1.5701f * uvcos) , 0.000f,
1.000f, (-0.1870f * uvcos) + (-0.4664f * uvsin), (-0.4664f * uvcos) - (-0.1870f * uvsin), 0.000f,
1.000f, ( 1.8556f * uvcos) , - ( 1.8556f * uvsin), 0.000f,
0.000f, 0.000f, 0.000f, m_alpha);
break;

case kCSTD_ITUR_BT_601:
case ColorSpaceBT601:
default:
csc = QMatrix4x4(
1.000f, ( 1.4030f * uvsin), ( 1.4030f * uvcos) , 0.000f,
Expand Down Expand Up @@ -167,10 +188,14 @@ void VideoColourSpace::Debug(void)
}
}

void VideoColourSpace::SetColourSpace(VideoCStd csp)
bool VideoColourSpace::SetColourSpace(MythColorSpace csp)
{
if (csp == m_colourSpace)
return false;
LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("New video colourspace: %1").arg(ToString(csp)));
m_colourSpace = csp;
Update();
return true;
}

void VideoColourSpace::SetStudioLevels(bool studio)
Expand Down
18 changes: 7 additions & 11 deletions mythtv/libs/libmythtv/videocolourspace.h
@@ -1,30 +1,26 @@
#ifndef VIDEOCOLOURSPACE_H
#define VIDEOCOLOURSPACE_H

// Qt
#include <QMap>
#include <QMatrix4x4>
#include "videoouttypes.h"

typedef enum VideoCStd
{
kCSTD_Unknown = 0,
kCSTD_ITUR_BT_601,
kCSTD_ITUR_BT_709,
kCSTD_SMPTE_240M,
} VideoCStd;
// MythTV
#include "mythframe.h"
#include "videoouttypes.h"

class VideoColourSpace : public QMatrix4x4
{
public:
explicit VideoColourSpace(VideoCStd colour_std = kCSTD_ITUR_BT_601);
explicit VideoColourSpace(MythColorSpace colour_std = ColorSpaceUnknown);
~VideoColourSpace() = default;

PictureAttributeSupported SupportedAttributes(void) const;
void SetSupportedAttributes(PictureAttributeSupported supported);
bool HasChanged(void);
int GetPictureAttribute(PictureAttribute attribute);
int SetPictureAttribute(PictureAttribute attribute, int value);
void SetColourSpace(VideoCStd csp = kCSTD_Unknown);
bool SetColourSpace(MythColorSpace csp);
void SetAlpha(int value);

private:
Expand All @@ -49,7 +45,7 @@ class VideoColourSpace : public QMatrix4x4
float m_saturation;
float m_hue;
float m_alpha;
VideoCStd m_colourSpace;
MythColorSpace m_colourSpace;
};

#endif
2 changes: 2 additions & 0 deletions mythtv/libs/libmythtv/videoout_opengl.cpp
Expand Up @@ -512,6 +512,8 @@ void VideoOutputOpenGL::ProcessFrame(VideoFrame *frame, OSD */*osd*/,
if (sw_frame && deint_proc && !m_deinterlaceBeforeOSD && !pauseframe && !dummy)
m_deintFilter->ProcessFrame(frame, scan);

videoColourSpace.SetColourSpace(frame->colorspace);

if (gl_videochain && sw_frame && !dummy)
gl_videochain->UpdateInputFrame(frame);

Expand Down
25 changes: 18 additions & 7 deletions mythtv/libs/libmythtv/videoout_vdpau.cpp
Expand Up @@ -411,6 +411,12 @@ void VideoOutputVDPAU::ProcessFrame(VideoFrame *frame, OSD */*osd*/,
if (!m_checked_surface_ownership && codec_is_std(video_codec_id))
ClaimVideoSurfaces();

// N.B. this overrides the filter option - but we now have a definitive view
// from the decoder, so use it.
if (frame)
if (videoColourSpace.SetColourSpace(frame->colorspace))
UpdateCSCMatrix();

m_pip_ready = false;
ShowPIPs(frame, pipPlayers);
}
Expand Down Expand Up @@ -905,16 +911,21 @@ void VideoOutputVDPAU::InitPictureAttributes(void)
"BT.601" : "BT.709"));
}

if (m_colorspace != VDP_COLOR_STANDARD_ITUR_BT_601)
{
videoColourSpace.SetColourSpace((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601)
? kCSTD_ITUR_BT_601 : kCSTD_ITUR_BT_709);
}
m_render->SetCSCMatrix(m_video_mixer, videoColourSpace.data());
videoColourSpace.SetColourSpace((m_colorspace == VDP_COLOR_STANDARD_ITUR_BT_601)
? ColorSpaceBT601 : ColorSpaceBT709);
UpdateCSCMatrix();
}
m_lock.unlock();
}

void VideoOutputVDPAU::UpdateCSCMatrix(void)
{
m_lock.lock();
if (m_render && m_video_mixer)
m_render->SetCSCMatrix(m_video_mixer, videoColourSpace.data());
m_lock.unlock();
}

int VideoOutputVDPAU::SetPictureAttribute(PictureAttribute attribute,
int newValue)
{
Expand All @@ -924,7 +935,7 @@ int VideoOutputVDPAU::SetPictureAttribute(PictureAttribute attribute,
m_lock.lock();
newValue = videoColourSpace.SetPictureAttribute(attribute, newValue);
if (newValue >= 0)
m_render->SetCSCMatrix(m_video_mixer, videoColourSpace.data());
UpdateCSCMatrix();
m_lock.unlock();
return newValue;
}
Expand Down
1 change: 1 addition & 0 deletions mythtv/libs/libmythtv/videoout_vdpau.h
Expand Up @@ -108,6 +108,7 @@ class VideoOutputVDPAU : public VideoOutput
void DeinitPIPS(void);
void DeinitPIPLayer(void);
void ParseOptions(void);
void UpdateCSCMatrix(void);

Window m_win;
MythRenderVDPAU *m_render;
Expand Down

0 comments on commit 1d39f1a

Please sign in to comment.