MythTV  master
videocolourspace.cpp
Go to the documentation of this file.
1 // MythTV
2 #include "mythcorecontext.h"
3 #include "mythlogging.h"
4 #include "mythdisplay.h"
5 #include "mythavutil.h"
6 #include "mythmainwindow.h"
7 #include "videocolourspace.h"
8 
9 // libavutil
10 extern "C" {
11 #include "libavutil/pixfmt.h"
12 #include "libavutil/pixdesc.h"
13 }
14 
15 // Std
16 #include <cmath>
17 
19  {{{0.640F, 0.330F}, {0.300F, 0.600F}, {0.150F, 0.060F}}, {0.3127F, 0.3290F}};
21  {{{0.630F, 0.340F}, {0.310F, 0.595F}, {0.155F, 0.070F}}, {0.3127F, 0.3290F}};
23  {{{0.640F, 0.330F}, {0.290F, 0.600F}, {0.150F, 0.060F}}, {0.3127F, 0.3290F}};
25  {{{0.708F, 0.292F}, {0.170F, 0.797F}, {0.131F, 0.046F}}, {0.3127F, 0.3290F}};
26 
27 #define LOC QString("ColourSpace: ")
28 
58  : ReferenceCounter("Colour"),
59  m_parent(Parent)
60 {
61  if (m_parent)
62  {
63  m_parent->IncrRef();
72  }
73  else
74  {
79  m_dbSettings[kPictureAttribute_Range] = static_cast<int>(gCoreContext->GetBoolSetting("GUIRGBLevels", true));
80  m_primariesMode = toPrimariesMode(gCoreContext->GetSetting("ColourPrimariesMode", "auto"));
81  }
82 
88 
89  // This isn't working as intended (most notable on OSX internal display).
90  // Presumably the driver is expecting sRGB/Rec709 and handles any final
91  // conversion to the display's colourspace.
92  /*
93  if (HasMythMainWindow())
94  {
95  MythDisplay* display = MythDisplay::AcquireRelease();
96  MythEDID& edid = display->GetEDID();
97  // We assume sRGB/Rec709 by default
98  bool custom = edid.Valid() && !edid.IsSRGB();
99  bool likesrgb = custom && edid.IsLikeSRGB() && m_primariesMode != PrimariesExact;
100  if (custom)
101  {
102  // Use sRGB if we don't want exact matching (i.e. close is good enough)
103  // and the display primaries are similar to sRGB.
104  if (likesrgb && qFuzzyCompare(edid.Gamma() + 1.0F, 2.2F + 1.0F))
105  {
106  LOG(VB_PLAYBACK, LOG_INFO, LOC + "sRGB primaries preferred as close match to display primaries");
107  }
108  else
109  {
110  m_customDisplayGamma = edid.Gamma();
111  m_customDisplayPrimaries = new ColourPrimaries;
112  MythEDID::Primaries displayprimaries = edid.ColourPrimaries();
113  memcpy(m_customDisplayPrimaries, &displayprimaries, sizeof(ColourPrimaries));
114  }
115  }
116  MythDisplay::AcquireRelease(false);
117  }
118  */
119  m_updatesDisabled = false;
120  Update();
121 }
122 
124 {
126  if (m_parent)
127  m_parent->DecrRef();
128 }
129 
131 {
132  return m_supportedAttributes;
133 }
134 
141 {
142  m_supportedAttributes = Supported;
143  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("PictureAttributes: %1").arg(toString(m_supportedAttributes)));
144 }
145 
147 {
148  if (m_dbSettings.contains(Attribute))
149  return m_dbSettings.value(Attribute);
150  return -1;
151 }
152 
155 {
156  if (!(m_supportedAttributes & toMask(Attribute)))
157  return -1;
158 
159  Value = std::min(std::max(Value, 0), 100);
160 
161  switch (Attribute)
162  {
164  SetBrightness(Value);
165  break;
167  SetContrast(Value);
168  break;
170  SetSaturation(Value);
171  break;
173  SetHue(Value);
174  break;
175  default:
176  Value = -1;
177  }
178 
179  emit PictureAttributeChanged(Attribute, Value);
180 
181  if (Value >= 0)
182  SaveValue(Attribute, Value);
183 
184  return Value;
185 }
186 
194 {
195  if (m_updatesDisabled)
196  return;
197 
198  // build an RGB to YCbCr conversion matrix from first principles
199  // and then invert it for the YCbCr to RGB conversion
200  std::vector<float> rgb;
201  switch (static_cast<AVColorSpace>(m_colourSpace))
202  {
203  case AVCOL_SPC_RGB: rgb = { 1.0000F, 1.0000F, 1.0000F }; break;
204  case AVCOL_SPC_BT709: rgb = { 0.2126F, 0.7152F, 0.0722F }; break;
205  case AVCOL_SPC_FCC: rgb = { 0.30F, 0.59F, 0.11F }; break;
206  case AVCOL_SPC_BT470BG:
207  case AVCOL_SPC_SMPTE170M: rgb = { 0.299F, 0.587F, 0.114F }; break;
208  case AVCOL_SPC_SMPTE240M: rgb = { 0.212F, 0.701F, 0.087F }; break;
209  case AVCOL_SPC_YCOCG: rgb = { 0.25F, 0.5F, 0.25F }; break;
210  case AVCOL_SPC_BT2020_CL:
211  case AVCOL_SPC_BT2020_NCL: rgb = { 0.2627F, 0.6780F, 0.0593F }; break;
212  case AVCOL_SPC_UNSPECIFIED:
213  case AVCOL_SPC_RESERVED:
214  case AVCOL_SPC_SMPTE2085:
215  case AVCOL_SPC_CHROMA_DERIVED_CL:
216  case AVCOL_SPC_CHROMA_DERIVED_NCL:
217  case AVCOL_SPC_ICTCP:
218  default: rgb = { 0.2126F, 0.7152F, 0.0722F }; //Rec.709
219  }
220 
221  float bs = rgb[2] == 1.0F ? 0.0F : 0.5F / (rgb[2] - 1.0F);
222  float rs = rgb[0] == 1.0F ? 0.0F : 0.5F / (rgb[0] - 1.0F);
223  QMatrix4x4 rgb2yuv( rgb[0], rgb[1], rgb[2], 0.0F,
224  bs * rgb[0], bs * rgb[1], 0.5F, 0.0F,
225  0.5F, rs * rgb[1], rs * rgb[2], 0.0F,
226  0.0F, 0.0F, 0.0F, m_alpha);
227 
228  // TODO check AVCOL_SPC_RGB
229  if (m_colourSpace == AVCOL_SPC_YCOCG)
230  {
231  rgb2yuv = QMatrix4x4(0.25F, 0.50F, 0.25F, 0.0F,
232  -0.25F, 0.50F, -0.25F, 0.0F,
233  0.50F, 0.00F, -0.50F, 0.0F,
234  0.00F, 0.00F, 0.00F, m_alpha);
235  }
236  QMatrix4x4 yuv2rgb = rgb2yuv.inverted();
237 
238  // scale the chroma values for saturation
239  yuv2rgb.scale(1.0F, m_saturation, m_saturation);
240  // rotate the chroma for hue - this is a rotation around the 'Y' (luminance) axis
241  yuv2rgb.rotate(m_hue, 1.0F, 0.0F, 0.0F);
242  // denormalise chroma
243  yuv2rgb.translate(0.0F, -0.5F, -0.5F);
244  // Levels adjustment
245  // This is a no-op when using full range MJPEG sources and full range output
246  // or 'standard' limited range MPEG sources with limited range output.
247  // N.B all of the quantization parameters scale perfectly between the different
248  // standards and bitdepths (i.e. 709 8 and 10 bit, 2020 10 and 12bit).
249  // In the event that we are displaying a downsampled format, the following
250  // also effectively limits the precision in line with that loss in precision.
251  // For example, YUV420P10 is downsampled by removing the 2 lower bits of
252  // precision. We identify the resultant YUV420P frame as 8bit and calculate
253  // the quantization/range accordingly.
254  bool expand = (m_range == AVCOL_RANGE_MPEG) && m_fullRange;
255  bool contract = (m_range == AVCOL_RANGE_JPEG) && !m_fullRange;
256  bool noop = !expand && !contract;
257  float depth = (1 << m_colourSpaceDepth) - 1;
258  float blacklevel = 16 << (m_colourSpaceDepth - 8);
259  float lumapeak = 235 << (m_colourSpaceDepth - 8);
260  float chromapeak = 240 << (m_colourSpaceDepth - 8);
261  float luma_scale = noop ? 1.0F : (expand ? depth / (lumapeak - blacklevel) : (lumapeak - blacklevel) / depth);
262  float chroma_scale = noop ? 1.0F : (expand ? depth / (chromapeak - blacklevel) : (chromapeak - blacklevel) / depth);
263  float offset = noop ? 0.0F : (expand ? -blacklevel / depth : blacklevel / depth);
264 
265  setToIdentity();
267  scale(m_contrast);
268  this->operator *= (yuv2rgb);
269  scale(luma_scale, chroma_scale, chroma_scale);
270  translate(offset, offset, offset);
271 
272  // Scale when needed for 10/12/16bit fixed point data
273  // Raw 10bit video is represented as XXXXXXXX:XX000000
274  // Raw 12bit video is XXXXXXXX:XXXX0000
275  // Raw 16bit video is XXXXXXXX:XXXXXXXX
276  // and these formats are returned by FFmpeg when software decoding
277  // so we need to shift by the appropriate number of 'bits' (actually a float in the shader)
278  // Hardware decoders seem to return 'corrected' values
279  // i.e. 10bit as XXXXXXXXXX for both direct rendering and copy back.
280  // Works for NVDEC and VAAPI. VideoToolBox untested.
281  if ((m_colourSpaceDepth > 8) && !m_colourShifted)
282  {
283  float scaler = 65535.0F / ((1 << m_colourSpaceDepth) -1);
284  scale(scaler);
285  }
286  static_cast<QMatrix4x4*>(this)->operator = (this->transposed());
287 
288  // check for a change in primaries conversion. This will need a recompile
289  // of the shaders - not just a parameter update.
290  float tmpsrcgamma = m_colourGamma;
291  float tmpdspgamma = m_displayGamma;
292  QMatrix4x4 tmpmatrix = m_primaryMatrix;
294  bool primchanged = !qFuzzyCompare(tmpsrcgamma, m_colourGamma) ||
295  !qFuzzyCompare(tmpdspgamma, m_displayGamma) ||
296  !qFuzzyCompare(tmpmatrix, m_primaryMatrix);
297  Debug();
298  emit Updated(primchanged);
299 }
300 
302 {
303  bool primary = !m_primaryMatrix.isIdentity();
304 
305  LOG(VB_PLAYBACK, LOG_DEBUG, LOC +
306  QString("Brightness: %1 Contrast: %2 Saturation: %3 Hue: %4 Alpha: %5 Range: %6 Primary: %7")
307  .arg(static_cast<qreal>(m_brightness), 2, 'f', 4, QLatin1Char('0'))
308  .arg(static_cast<qreal>(m_contrast) , 2, 'f', 4, QLatin1Char('0'))
309  .arg(static_cast<qreal>(m_saturation), 2, 'f', 4, QLatin1Char('0'))
310  .arg(static_cast<qreal>(m_hue) , 2, 'f', 4, QLatin1Char('0'))
311  .arg(static_cast<qreal>(m_alpha) , 2, 'f', 4, QLatin1Char('0'))
312  .arg(m_fullRange ? "Full" : "Limited")
313  .arg(primary));
314 
315  if (VERBOSE_LEVEL_CHECK(VB_PLAYBACK, LOG_DEBUG))
316  {
317  QString stream;
318  QDebug debug(&stream);
319  debug << *this;
320  if (primary)
322  LOG(VB_PLAYBACK, LOG_DEBUG, stream);
323  }
324 }
325 
333 {
334  if (!Frame)
335  return false;
336 
337  int csp = Frame->colorspace;
338  int primary = Frame->colorprimaries;
339  int transfer = Frame->colortransfer;
340  int raw = csp;
341  VideoFrameType frametype = Frame->codec;
342  VideoFrameType softwaretype = PixelFormatToFrameType(static_cast<AVPixelFormat>(Frame->sw_pix_fmt));
343 
344  // workaround for NVDEC. NVDEC defaults to a colorspace of 0 - which happens
345  // to equate to RGB. In testing, NVDEC reports the same colourspace as FFmpeg
346  // software decode for MPEG2, MPEG4, H.264, HEVC and VP8. VP9 seems to go wrong (with limited samples)
347  bool forced = false;
348  if (csp == AVCOL_SPC_RGB && (format_is_yuv(frametype) || frametype == FMT_NVDEC))
349  {
350  forced = true;
351  csp = AVCOL_SPC_UNSPECIFIED;
352  }
353  int range = Frame->colorrange;
354  if (range == AVCOL_RANGE_UNSPECIFIED)
355  range = AVCOL_RANGE_MPEG;
356  int depth = ColorDepth(format_is_hw(frametype) ? softwaretype : frametype);
357  if (csp == AVCOL_SPC_UNSPECIFIED)
358  csp = (Frame->width < 1280) ? AVCOL_SPC_BT470BG : AVCOL_SPC_BT709;
359  if (primary == AVCOL_PRI_UNSPECIFIED)
360  primary = (Frame->width < 1280) ? AVCOL_PRI_BT470BG : AVCOL_PRI_BT709;
361  if (transfer == AVCOL_TRC_UNSPECIFIED)
362  transfer = (Frame->width < 1280) ? AVCOL_TRC_GAMMA28 : AVCOL_TRC_BT709;
363  if ((csp == m_colourSpace) && (m_colourSpaceDepth == depth) &&
364  (m_range == range) && (m_colourShifted == Frame->colorshifted) &&
365  (primary == m_colourPrimaries))
366  {
367  return false;
368  }
369 
370  m_colourSpace = csp;
371  m_colourSpaceDepth = depth;
372  m_range = range;
373  m_colourShifted = Frame->colorshifted;
374  m_colourPrimaries = primary;
375  m_colourTransfer = transfer;
376 
377  if (forced)
378  LOG(VB_GENERAL, LOG_WARNING, LOC + QString("Forcing inconsistent colourspace - frame format %1")
379  .arg(format_description(Frame->codec)));
380 
381  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Input : %1(%2) Depth:%3 %4Range:%5")
382  .arg(av_color_space_name(static_cast<AVColorSpace>(m_colourSpace)))
383  .arg(m_colourSpace == raw ? "Detected" : "Guessed")
384  .arg(m_colourSpaceDepth)
385  .arg((m_colourSpaceDepth > 8) ? (m_colourShifted ? "(Pre-scaled) " : "(Fixed point) ") : "")
386  .arg((AVCOL_RANGE_JPEG == m_range) ? "Full" : "Limited"));
387  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Input : Primaries:%1 Transfer: %2")
388  .arg(av_color_primaries_name(static_cast<AVColorPrimaries>(m_colourPrimaries)))
389  .arg(av_color_transfer_name(static_cast<AVColorTransferCharacteristic>(m_colourTransfer))));
390  LOG(VB_PLAYBACK, LOG_INFO, LOC + QString("Output: Range:%1 Primaries: %2")
391  .arg(m_fullRange ? "Full" : "Limited")
392  .arg(m_customDisplayPrimaries ? "Custom (screen)" :
393  av_color_primaries_name(static_cast<AVColorPrimaries>(m_displayPrimaries))));
394 
395  Update();
396 
397  if (!m_primaryMatrix.isIdentity())
398  {
399  LOG(VB_GENERAL, LOG_INFO, LOC + QString("Enabled colourspace primaries conversion from %1 to %2")
400  .arg(av_color_primaries_name(static_cast<AVColorPrimaries>(m_colourPrimaries)))
401  .arg(m_customDisplayPrimaries ? "Custom (screen)" :
402  av_color_primaries_name(static_cast<AVColorPrimaries>(m_displayPrimaries))));
403  }
404  return true;
405 }
406 
407 void VideoColourSpace::SetFullRange(bool FullRange)
408 {
409  m_fullRange = FullRange;
410  Update();
411 }
412 
414 {
415  m_brightness = (Value * 0.02F) - 1.0F;
416  Update();
417 }
418 
420 {
421  m_contrast = Value * 0.02F;
422  Update();
423 }
424 
426 {
427  m_hue = Value * -3.6F;
428  Update();
429 }
430 
432 {
433  m_saturation = Value * 0.02F;
434  Update();
435 }
436 
438 {
439  m_alpha = 100.0F / Value;
440  Update();
441 }
442 
444 {
445  QStringList result;
446  if (m_primaryMatrix.isIdentity())
447  return result;
448 
449  result << "COLOURMAPPING";
450  return result;
451 }
452 
454 {
455  return m_primaryMatrix;
456 }
457 
459 {
460  return m_colourGamma;
461 }
462 
464 {
465  return m_displayGamma;
466 }
467 
469 {
470  return m_primariesMode;
471 }
472 
474 {
475  m_primariesMode = Mode;
476  Update();
477 }
478 
480 void VideoColourSpace::SaveValue(PictureAttribute AttributeType, int Value)
481 {
482  // parent owns the database settings
483  if (m_parent)
484  return;
485 
486  QString dbName;
487  if (kPictureAttribute_Brightness == AttributeType)
488  dbName = "PlaybackBrightness";
489  else if (kPictureAttribute_Contrast == AttributeType)
490  dbName = "PlaybackContrast";
491  else if (kPictureAttribute_Colour == AttributeType)
492  dbName = "PlaybackColour";
493  else if (kPictureAttribute_Hue == AttributeType)
494  dbName = "PlaybackHue";
495 
496  if (!dbName.isEmpty())
497  gCoreContext->SaveSetting(dbName, Value);
498 
499  m_dbSettings[AttributeType] = Value;
500 }
501 
503 {
504  // Default to identity
505  QMatrix4x4 result;
506 
507  // User isn't interested in quality
509  return result;
510 
511  auto source = static_cast<AVColorPrimaries>(Source);
512  auto dest = static_cast<AVColorPrimaries>(Dest);
513  auto custom = m_customDisplayPrimaries != nullptr;
514 
515  // No-op
516  if (!custom && (source == dest))
517  return result;
518 
519  ColourPrimaries srcprimaries = GetPrimaries(source, m_colourGamma);
521  if (custom)
522  {
523  dstprimaries = *m_customDisplayPrimaries;
525  }
526 
527  // If 'exact' is not requested and the primaries and gamma are similar, then
528  // ignore. Note: 0.021F should cover any differences between Rec.709/sRGB and Rec.610
529  if ((m_primariesMode == PrimariesRelaxed) && qFuzzyCompare(m_colourGamma + 1.0F, m_displayGamma + 1.0F) &&
530  Similar(srcprimaries, dstprimaries, 0.021F))
531  {
532  return result;
533  }
534 
535  return (RGBtoXYZ(srcprimaries) * RGBtoXYZ(dstprimaries).inverted());
536 }
537 
539 {
540  auto primary = static_cast<AVColorPrimaries>(Primary);
541  Gamma = 2.2F;
542  switch (primary)
543  {
544  case AVCOL_PRI_BT470BG:
545  case AVCOL_PRI_BT470M: return kBT610_625;
546  case AVCOL_PRI_SMPTE170M:
547  case AVCOL_PRI_SMPTE240M: return kBT610_525;
548  case AVCOL_PRI_BT2020: Gamma = 2.4F; return kBT2020;
549  default: return kBT709;
550  }
551 }
552 
553 bool VideoColourSpace::Similar(const ColourPrimaries &First, const ColourPrimaries &Second, float Fuzz)
554 {
555  auto cmp = [=](float One, float Two) { return (abs(One - Two) < Fuzz); };
556  return cmp(First.primaries[0][0], Second.primaries[0][0]) &&
557  cmp(First.primaries[0][1], Second.primaries[0][1]) &&
558  cmp(First.primaries[1][0], Second.primaries[1][0]) &&
559  cmp(First.primaries[1][1], Second.primaries[1][1]) &&
560  cmp(First.primaries[2][0], Second.primaries[2][0]) &&
561  cmp(First.primaries[2][1], Second.primaries[2][1]) &&
562  cmp(First.whitepoint[0], Second.whitepoint[0]) &&
563  cmp(First.whitepoint[1], Second.whitepoint[1]);
564 }
565 
566 inline float CalcBy(const float p[3][2], const float w[2])
567 {
568  float val = ((1-w[0])/w[1] - (1-p[0][0])/p[0][1]) * (p[1][0]/p[1][1] - p[0][0]/p[0][1]) -
569  (w[0]/w[1] - p[0][0]/p[0][1]) * ((1-p[1][0])/p[1][1] - (1-p[0][0])/p[0][1]);
570  val /= ((1-p[2][0])/p[2][1] - (1-p[0][0])/p[0][1]) * (p[1][0]/p[1][1] - p[0][0]/p[0][1]) -
571  (p[2][0]/p[2][1] - p[0][0]/p[0][1]) * ((1-p[1][0])/p[1][1] - (1-p[0][0])/p[0][1]);
572  return val;
573 }
574 
575 inline float CalcGy(const float p[3][2], const float w[2], const float By)
576 {
577  float val = w[0]/w[1] - p[0][0]/p[0][1] - By * (p[2][0]/p[2][1] - p[0][0]/p[0][1]);
578  val /= p[1][0]/p[1][1] - p[0][0]/p[0][1];
579  return val;
580 }
581 
582 inline float CalcRy(const float By, const float Gy)
583 {
584  return 1.0F - Gy - By;
585 }
586 
595 {
596  float By = CalcBy(Primaries.primaries, Primaries.whitepoint);
597  float Gy = CalcGy(Primaries.primaries, Primaries.whitepoint, By);
598  float Ry = CalcRy(By, Gy);
599 
600  float temp[4][4];
601  temp[0][0] = Ry * Primaries.primaries[0][0] / Primaries.primaries[0][1];
602  temp[0][1] = Gy * Primaries.primaries[1][0] / Primaries.primaries[1][1];
603  temp[0][2] = By * Primaries.primaries[2][0] / Primaries.primaries[2][1];
604  temp[1][0] = Ry;
605  temp[1][1] = Gy;
606  temp[1][2] = By;
607  temp[2][0] = Ry / Primaries.primaries[0][1] * (1- Primaries.primaries[0][0] - Primaries.primaries[0][1]);
608  temp[2][1] = Gy / Primaries.primaries[1][1] * (1- Primaries.primaries[1][0] - Primaries.primaries[1][1]);
609  temp[2][2] = By / Primaries.primaries[2][1] * (1- Primaries.primaries[2][0] - Primaries.primaries[2][1]);
610  temp[0][3] = temp[1][3] = temp[2][3] = temp[3][0] = temp[3][1] = temp[3][2] = 0.0F;
611  temp[3][3] = 1.0F;
612  return QMatrix4x4(temp[0]);
613 }
float CalcBy(const float p[3][2], const float w[2])
PrimariesMode GetPrimariesMode(void)
float CalcGy(const float p[3][2], const float w[2], const float By)
static const ColourPrimaries kBT610_525
VideoColourSpace contains a QMatrix4x4 that can convert YCbCr data to RGB.
PrimariesMode
static bool format_is_yuv(VideoFrameType Type)
Definition: mythframe.h:114
~VideoColourSpace() override
float GetColourGamma(void) const
QMap< PictureAttribute, int > m_dbSettings
void SetPrimariesMode(PrimariesMode Mode)
PictureAttributeSupported
QString toString(MarkTypes type)
void SaveSetting(const QString &key, int newValue)
General purpose reference counter.
void SetSaturation(int Value)
int GetPictureAttribute(PictureAttribute Attribute)
VideoFrameType PixelFormatToFrameType(AVPixelFormat fmt)
Definition: mythavutil.cpp:68
VideoFrameType
Definition: mythframe.h:23
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
void SetFullRange(bool FullRange)
int ColorDepth(int Format)
Return the color depth for the given MythTV frame format.
Definition: mythframe.cpp:808
#define LOC
void PictureAttributeChanged(PictureAttribute Attribute, int Value)
static const ColourPrimaries kBT610_625
VideoColourSpace(VideoColourSpace *Parent=nullptr)
QMatrix4x4 GetPrimaryMatrix(void)
virtual int IncrRef(void)
Increments reference count.
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:14
void SetAlpha(int Value)
QString GetSetting(const QString &key, const QString &defaultval="")
QStringList GetColourMappingDefines(void)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
static void yuv2rgb(int y, int cr, int cb, eu8 *r, eu8 *g, eu8 *b)
Definition: pxsup2dast.c:200
static void rgb2yuv(eu8 r, eu8 g, eu8 b, eu8 *y, eu8 *cr, eu8 *cb)
Definition: pxsup2dast.c:213
PictureAttribute
Definition: videoouttypes.h:87
ColourPrimaries * m_customDisplayPrimaries
void SetHue(int Value)
static const ColourPrimaries kBT709
void Updated(bool PrimariesChanged)
PictureAttributeSupported m_supportedAttributes
void SetBrightness(int Value)
void SetSupportedAttributes(PictureAttributeSupported Supported)
Enable the given set of picture attributes.
int GetNumSetting(const QString &key, int defaultval=0)
QMatrix4x4 GetPrimaryConversion(int Source, int Dest)
bool GetBoolSetting(const QString &key, bool defaultval=false)
VERBOSE_PREAMBLE Most debug(nodatabase, notimestamp, noextra)") VERBOSE_MAP(VB_GENERAL
static const ColourPrimaries kBT2020
PictureAttributeSupported toMask(PictureAttribute PictureAttribute)
VideoColourSpace * m_parent
static bool format_is_hw(VideoFrameType Type)
Definition: mythframe.h:72
PictureAttributeSupported SupportedAttributes(void) const
void SaveValue(PictureAttribute Attribute, int Value)
Save the PictureAttribute value to the database.
static ColourPrimaries GetPrimaries(int Primary, float &Gamma)
const char * format_description(VideoFrameType Type)
Definition: mythframe.cpp:33
int SetPictureAttribute(PictureAttribute Attribute, int Value)
Set the Value for the given PictureAttribute.
QMatrix4x4 m_primaryMatrix
void SetContrast(int Value)
void Update(void)
Update the matrix for the current settings and colourspace.
PrimariesMode m_primariesMode
bool UpdateColourSpace(const VideoFrame *Frame)
Set the current colourspace to use.
static QMatrix4x4 RGBtoXYZ(ColourPrimaries Primaries)
Create a conversion matrix for RGB to XYZ with the given primaries.
float CalcRy(const float By, const float Gy)
static bool Similar(const ColourPrimaries &First, const ColourPrimaries &Second, float Fuzz)
float GetDisplayGamma(void) const
PrimariesMode toPrimariesMode(const QString &Mode)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23