AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
ntv2csclut.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2card.h"
9 #include "ntv2devicefeatures.h"
10 #include "ntv2utils.h"
11 #include "ntv2registerexpert.h"
12 #include "ajabase/system/debug.h"
13 #include <math.h>
14 #include <assert.h>
15 #if defined (AJALinux)
17 #elif defined (MSWindows)
18  #pragma warning(disable: 4800)
19 #endif
20 #include <deque>
21 
22 #define HEX16(__x__) "0x" << hex << setw(16) << setfill('0') << uint64_t(__x__) << dec
23 #define INSTP(_p_) HEX16(uint64_t(_p_))
24 #define CSCFAIL(__x__) AJA_sERROR (AJA_DebugUnit_CSC, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
25 #define CSCWARN(__x__) AJA_sWARNING(AJA_DebugUnit_CSC, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
26 #define CSCNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_CSC, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
27 #define CSCINFO(__x__) AJA_sINFO (AJA_DebugUnit_CSC, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
28 #define CSCDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_CSC, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
29 
30 #define LUTFAIL(__x__) AJA_sERROR (AJA_DebugUnit_LUT, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
31 #define LUTWARN(__x__) AJA_sWARNING(AJA_DebugUnit_LUT, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
32 #define LUTNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_LUT, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
33 #define LUTINFO(__x__) AJA_sINFO (AJA_DebugUnit_LUT, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
34 #define LUTDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_LUT, INSTP(this) << "::" << AJAFUNC << ": " << __x__)
35 
36 using namespace std;
37 
38 
39 
40 // These static tables eliminate a lot of switch statements.
41 // CAUTION: These are predicated on NTV2Channel being ordinal (NTV2_CHANNEL1==0, NTV2_CHANNEL2==1, etc.)
42 
45 
48 
51 
54 
57 
60 
63 
64 static const ULWord gChannelCapabilities [] = {
73  0 };
74 
75 static const ULWord gChannelDmaLoad [] = {
84  0 };
85 
86 static const ULWord gChannelHostLoad [] = {
95  0 };
96 
98 // OEM Color Correction Methods (KHD-22 only )
99 //
101 {
102  if (IS_CHANNEL_INVALID(inChannel))
103  return false;
104  return WriteRegister (inChannel == NTV2_CHANNEL1 ? kRegCh1ColorCorrectionControl : kRegCh2ColorCorrectionControl,
106 
107 }
108 
110 {
111  if (IS_CHANNEL_INVALID (inChannel))
112  return false;
114  outMode, kRegMaskCCMode, kRegShiftCCMode);
115 }
116 
117 bool CNTV2Card::SetColorCorrectionOutputBank (const NTV2Channel inChannel, const ULWord inBank)
118 {
119  if (IS_CHANNEL_INVALID(inChannel))
120  return false;
121  if (GetNumSupported(kDeviceGetLUTVersion) == 2)
122  return SetLUTV2OutputBank(inChannel, inBank);
123  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
124  return SetLUTV3OutputBank(inChannel, inBank);
125 
126  switch(inChannel)
127  {
133  default: return false;
134  }
135 }
136 
137 bool CNTV2Card::SetLUTV2OutputBank (const NTV2Channel inChannel, const ULWord inBank)
138 {
139  if (IS_CHANNEL_INVALID(inChannel))
140  return false;
141  switch (inChannel)
142  {
151  default: return false;
152  }
153 }
154 
155 bool CNTV2Card::SetLUTV3OutputBank (const NTV2Channel inChannel, const ULWord inBank)
156 {
157  ULWord supported = 0;
158 
159  if (IS_CHANNEL_INVALID(inChannel))
160  return false;
161 
162  if (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
163  return false;
164  if ((inBank > 0) &&
165  (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3Banks2, shiftCCLUTV3Banks2) || (supported == 0)))
166  return false;
167  return WriteRegister(gChannelHostLoad[inChannel], inBank, maskCCLUTV3OutputBank, shiftCCLUTV3OutputBank);
168 }
169 
171 {
172  if (IS_CHANNEL_INVALID (inChannel))
173  return false;
174  if (GetNumSupported(kDeviceGetLUTVersion) == 2)
175  return GetLUTV2OutputBank(inChannel, outBank);
176  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
177  return GetLUTV3OutputBank(inChannel, outBank);
178 
179  switch(inChannel)
180  {
186  default: return false;
187  }
188 }
189 
190 bool CNTV2Card::GetLUTV2OutputBank (const NTV2Channel inChannel, ULWord & outBank)
191 {
192  if (IS_CHANNEL_INVALID(inChannel))
193  return false;
194  switch(inChannel)
195  {
204  default: return false;
205  }
206 }
207 
208 bool CNTV2Card::GetLUTV3OutputBank (const NTV2Channel inChannel, ULWord & outBank)
209 {
210  ULWord supported = 0;
211 
212  if (IS_CHANNEL_INVALID(inChannel))
213  return false;
214 
215  if (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
216  return false;
217 
218  return ReadRegister(gChannelHostLoad[inChannel], outBank, maskCCLUTV3OutputBank, shiftCCLUTV3OutputBank);
219 }
220 
222 {
223  if (GetNumSupported(kDeviceGetLUTVersion) == 2)
224  return SetLUTV2HostAccessBank(inValue);
225  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
226  return SetLUTV3HostAccessBank(inValue);
227 
228  switch(inValue)
229  {
234  if (::NTV2DeviceGetNumLUTs(GetDeviceID()) == 5 || GetDeviceID() == DEVICE_ID_IO4KUFC)
236  return false;
237  //Configure LUTs 1 and 2
240 
245  if (::NTV2DeviceGetNumLUTs(GetDeviceID()) == 5 || GetDeviceID() == DEVICE_ID_IO4KUFC)
247  return false;
248  //Configure LUTs 3 and 4
251 
258 
259  default: return false;
260  }
261  }
262 
264 {
265  switch(inValue)
266  {
269 
272 
275 
278 
281 
284 
287 
290 
291  default: return false;
292  }
293 }
294 
296 {
297  ULWord channel = 0;
298  ULWord bank = 0;
299  ULWord supported = 0;
300 
301  switch(inValue)
302  {
303  case NTV2_CCHOSTACCESS_CH1BANK0: channel = 0; bank = 0; break;
304  case NTV2_CCHOSTACCESS_CH1BANK1: channel = 0; bank = 1; break;
305 
306  case NTV2_CCHOSTACCESS_CH2BANK0: channel = 1; bank = 0; break;
307  case NTV2_CCHOSTACCESS_CH2BANK1: channel = 1; bank = 1; break;
308 
309  case NTV2_CCHOSTACCESS_CH3BANK0: channel = 2; bank = 0; break;
310  case NTV2_CCHOSTACCESS_CH3BANK1: channel = 2; bank = 1; break;
311 
312  case NTV2_CCHOSTACCESS_CH4BANK0: channel = 3; bank = 0; break;
313  case NTV2_CCHOSTACCESS_CH4BANK1: channel = 3; bank = 1; break;
314 
315  case NTV2_CCHOSTACCESS_CH5BANK0: channel = 4; bank = 0; break;
316  case NTV2_CCHOSTACCESS_CH5BANK1: channel = 4; bank = 1; break;
317 
318  case NTV2_CCHOSTACCESS_CH6BANK0: channel = 5; bank = 0; break;
319  case NTV2_CCHOSTACCESS_CH6BANK1: channel = 5; bank = 1; break;
320 
321  case NTV2_CCHOSTACCESS_CH7BANK0: channel = 6; bank = 0; break;
322  case NTV2_CCHOSTACCESS_CH7BANK1: channel = 6; bank = 1; break;
323 
324  case NTV2_CCHOSTACCESS_CH8BANK0: channel = 7; bank = 0; break;
325  case NTV2_CCHOSTACCESS_CH8BANK1: channel = 7; bank = 1; break;
326 
327  default: return false;
328  }
329 
330  if (!ReadRegister(gChannelCapabilities[channel], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
331  return false;
332  if ((bank > 0) &&
333  (!ReadRegister(gChannelCapabilities[channel], supported, maskCCLUTV3Banks2, shiftCCLUTV3Banks2) || (supported == 0)))
334  return false;
335 
336  return WriteRegister(gChannelHostLoad[channel], bank, maskCCLUTV3BankSelect, shiftCCLUTV3BankSelect);
337 }
338 
340 {
341  if (IS_CHANNEL_INVALID(inChannel))
342  return false;
343  if (GetNumSupported(kDeviceGetLUTVersion) == 2)
344  return GetLUTV2HostAccessBank(outValue, inChannel);
345  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
346  return GetLUTV3HostAccessBank(outValue, inChannel);
347 
348  bool result (false);
349  ULWord regValue(0);
350  switch(inChannel)
351  {
352  case NTV2_CHANNEL1:
353  case NTV2_CHANNEL2:
355 
356  case NTV2_CHANNEL3:
357  case NTV2_CHANNEL4:
360  break;
361 
362  case NTV2_CHANNEL5:
365  break;
366 
367  default: break;
368  }
369  return result;
370 }
371 
373 {
374  if (IS_CHANNEL_INVALID(inChannel))
375  return false;
376 
377  ULWord tempVal (0);
378  bool result (false);
379  switch(inChannel)
380  {
381  case NTV2_CHANNEL1:
383  break;
384 
385  case NTV2_CHANNEL2:
388  break;
389 
390  case NTV2_CHANNEL3:
393  break;
394 
395  case NTV2_CHANNEL4:
398  break;
399 
400  case NTV2_CHANNEL5:
403  break;
404 
405  case NTV2_CHANNEL6:
408  break;
409 
410  case NTV2_CHANNEL7:
413  break;
414 
415  case NTV2_CHANNEL8:
418  break;
419 
420  default: break;
421  }
422  return result;
423 }
424 
426 {
427  ULWord supported = 0;
428 
429  if (IS_CHANNEL_INVALID(inChannel))
430  return false;
431 
432  if (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
433  return false;
434 
436 }
437 
438 bool CNTV2Card::SetColorCorrectionSaturation (const NTV2Channel inChannel, const ULWord inValue)
439 {
440  if (IS_CHANNEL_INVALID(inChannel))
441  return false;
442 
443  return WriteRegister (inChannel == NTV2_CHANNEL1 ? kRegCh1ColorCorrectionControl : kRegCh2ColorCorrectionControl,
445 }
446 
448 {
449  if (IS_CHANNEL_INVALID(inChannel))
450  return false;
451 
452  return ReadRegister (inChannel == NTV2_CHANNEL1 ? kRegCh1ColorCorrectionControl : kRegCh2ColorCorrectionControl,
454 }
455 
457 {
458  return WriteRegister(kRegCh1ColorCorrectionControl, (ULWord)lutSelect, kRegMaskLUTSelect, kRegShiftLUTSelect);
459 }
460 
462 {
464 }
465 
467 {
468  ULWord has12BitLUTSupport(0);
469  ULWord supported = 0;
470  bool result = false;
471 
472  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
473  {
474  if (GetIndexForNTV2Channel(inChannel) >= GetNumSupported(kDeviceGetNumLUTs))
475  return false;
476  result = ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3Depth12, shiftCCLUTV3Depth12) && (supported != 0);
477  }
478  else
479  {
480  result = ReadRegister(kRegLUTV2Control, has12BitLUTSupport, kRegMask12BitLUTSupport, kRegShift12BitLUTSupport) &&
481  (has12BitLUTSupport ? true : false);
482  }
483 
484  return result;
485 }
486 
487 bool CNTV2Card::Set12BitLUTPlaneSelect(NTV2LUTPlaneSelect inLUTPlaneSelect, const NTV2Channel inChannel)
488 {
489  ULWord supported = 0;
490  ULWord iChn = 0;
491  bool result = false;
492 
493  if(!Has12BitLUTSupport())
494  return false;
495 
496  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
497  {
498  if (GetIndexForNTV2Channel(inChannel) < GetNumSupported(kDeviceGetNumLUTs))
499  {
500  if (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
501  return false;
502  result = WriteRegister(gChannelHostLoad[inChannel], inLUTPlaneSelect, maskLUTV3PlaneSelect, shiftLUTV3PlaneSelect);
503  }
504  else
505  {
506  for (iChn = 0; iChn < GetNumSupported(kDeviceGetNumLUTs); iChn++)
507  {
508  if (!ReadRegister(gChannelCapabilities[iChn], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
509  return false;
510  result = WriteRegister(gChannelHostLoad[iChn], inLUTPlaneSelect, maskLUTV3PlaneSelect, shiftLUTV3PlaneSelect);
511  if (!result) break;
512  }
513  }
514  }
515  else
516  {
517  result = WriteRegister(kRegLUTV2Control, inLUTPlaneSelect, kRegMask12BitLUTPlaneSelect, kRegShift12BitLUTPlaneSelect);
518  }
519 
520  return result;
521 }
522 
523 bool CNTV2Card::Get12BitLUTPlaneSelect(NTV2LUTPlaneSelect & outLUTPlaneSelect, const NTV2Channel inChannel)
524 {
525  ULWord supported = 0;
526  bool result = false;
527 
528  if(!Has12BitLUTSupport())
529  return false;
530 
531  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
532  {
533  if (GetIndexForNTV2Channel(inChannel) >= GetNumSupported(kDeviceGetNumLUTs))
534  return false;
535 
536  if (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
537  return false;
538  result = CNTV2DriverInterface::ReadRegister(gChannelHostLoad[inChannel], outLUTPlaneSelect,
540  }
541  else
542  {
543  result = CNTV2DriverInterface::ReadRegister(kRegLUTV2Control, outLUTPlaneSelect,
545  }
546 
547  return result;
548 }
549 
551 
552 
553 bool CNTV2Card::SetColorSpaceMethod (const NTV2ColorSpaceMethod inCSCMethod, const NTV2Channel inChannel)
554 {
555  if (IS_CHANNEL_INVALID (inChannel))
556  return false;
557  if (::NTV2DeviceGetNumCSCs (_boardID) == 0)
558  return false;
559 
560  if (::NTV2DeviceCanDoEnhancedCSC (_boardID))
561  {
562  ULWord value (0);
563 
564  switch (inCSCMethod)
565  {
567  // Disable enhanced mode and 4K
568  break;
570  // Enable enhanced mode, but not 4K
572  break;
574  // 4K mode uses a block of four CSCs. You must set the first converter in the group.
575  if ((inChannel != NTV2_CHANNEL1) && (inChannel != NTV2_CHANNEL5))
576  return false;
577  // Enable both enhanced mode and 4K
579  break;
580  default:
581  return false;
582  }
583 
584  // Send the new control value to the hardware
586 
587  return true;
588  }
589  else
590  {
591  // It's not an error to set the original converters to the original method
592  if (inCSCMethod == NTV2_CSC_Method_Original)
593  return true;
594  }
595 
596  return false;
597 }
598 
600 {
601  outMethod = NTV2_CSC_Method_Unimplemented;
602  if (IS_CHANNEL_INVALID(inChannel))
603  return false;
604  if (!::NTV2DeviceGetNumCSCs(_boardID))
605  return false;
606 
607  outMethod = NTV2_CSC_Method_Original;
608  if (!::NTV2DeviceCanDoEnhancedCSC(_boardID))
609  return true;
610 
611  ULWord tempVal (0);
612 
613  // Check the group leader first, since that's where the 4K status bit is for all...
615  return false;
616 
618  {
619  outMethod = NTV2_CSC_Method_Enhanced_4K; // The leader is in 4K, so the other group members are as well
620  return true;
621  }
622 
623  // Each CSC is operating independently, so read the control bits for the given channel
625  return false;
626 
627  if (tempVal & kK2RegMaskEnhancedCSCEnable)
628  outMethod = NTV2_CSC_Method_Enhanced;
629  return true;
630 }
631 
632 
634 {
636  GetColorSpaceMethod(result, inChannel);
637  return result;
638 }
639 
640 
642 {
643  if (IS_CHANNEL_INVALID (channel))
644  return false;
646 }
647 
648 
650 {
651  if (IS_CHANNEL_INVALID(inChannel))
652  return false;
654 }
655 
656 
657 // STATIC:
658 bool CNTV2Card::GenerateGammaTable (const NTV2LutType inLUTType, const int inBank, NTV2DoubleArray & outTable, const NTV2LutBitDepth inBitDepth)
659 {
660  static const double kGammaMac(1.8);
661  double gamma1(0.0), gamma2(0.0), scale(0.0), fullWhite(0.0), fullBlack(0.0), smpteWhite(0.0), smpteBlack(0.0);
662  uint32_t tableSize(0);
663 
664  // 10 Bit Notes
665  // 1020 / 0x3FC is full-range white on the wire since 0x3FF/1023 is illegal
666  // 4 / 0x4 is full-range black on the wire since 0x0/0 is illegal
667  // 940 / 0x3AC is smpte-range white
668  // 64 / 0x40 is smpte-range black
669 
670  // 12 Bit Notes
671  // 4080 / 0xFF0 is full-range white on the wire since 0xFFC/4092 is illegal
672  // 16 / 0x10 is full-range black on the wire since 0x0/0 is illegal
673  // 3760 / 0xEB0 is smpte-range white
674  // 256 / 0x100 is smpte-range black
675 
676  switch(inBitDepth)
677  {
678  default:
679  case NTV2_LUT10Bit:
680  fullWhite = 1023.0;
681  fullBlack = 0.0;
682  smpteWhite = 940.0;
683  smpteBlack = 64.0;
684  tableSize = 1024;
685  outTable.reserve(tableSize);
686  while (outTable.size() < tableSize)
687  outTable.push_back(double(0.0));
688  break;
689  case NTV2_LUT12Bit:
690  fullWhite = 4092.0;
691  fullBlack = 0.0;
692  smpteWhite = 3760.0;
693  smpteBlack = 256.0;
694  tableSize = 4096;
695  outTable.reserve(tableSize);
696  while (outTable.size() < tableSize)
697  outTable.push_back(double(0.0));
698  break;
699  }
700 
701  double smpteScale = (smpteWhite - smpteBlack) - 1.0;
702 
703 
704  switch (inLUTType)
705  {
706  // Linear
707  case NTV2_LUTLinear:
708  case NTV2_LUTUnknown: // huh?
709  case NTV2_LUTCustom:
710  default:
711  for (size_t ndx = 0; ndx < tableSize; ndx++)
712  outTable[ndx] = double(ndx);
713  break;
714 
715  // RGB Full Range <=> SMPTE Range
717  if (inBank == kLUTBank_FULL2SMPTE)
718  {
719  scale = (smpteWhite - smpteBlack) / (fullWhite - fullBlack);
720 
721  for (size_t ndx = 0; ndx < tableSize; ndx++)
722  outTable[ndx] = (double(ndx) * scale) + (smpteBlack - (scale * fullBlack));
723  }
724  else // inBank == kLUTBank_SMPTE2FULL
725  {
726  scale = (fullWhite - fullBlack) / (smpteWhite - smpteBlack);
727 
728  for (size_t ndx = 0; ndx < (uint32_t)smpteBlack; ndx++)
729  outTable[ndx] = fullBlack;
730 
731  for (size_t ndx = (uint32_t)smpteBlack; ndx < (uint32_t)smpteWhite; ndx++)
732  outTable[ndx] = (double(ndx) * scale) + ((uint32_t)fullBlack - (scale * (uint32_t)smpteBlack));
733 
734  for (size_t ndx = (uint32_t)smpteWhite; ndx < tableSize; ndx++)
735  outTable[ndx] = fullWhite;
736  }
737  break; // NTV2_LUTRGBRangeFull_SMPTE
738 
739  // kGammaMac <=> Rec 601 Gamma - Full Range
741  // "gamma" (the exponent) = srcGamma / dstGamma
742  gamma1 = (inBank == kLUTBank_RGB2YUV ? (kGammaMac / 2.2) : (2.2 / kGammaMac) );
743  for (size_t ndx = 0; ndx < tableSize; ndx++)
744  outTable[ndx] = fullWhite * ::pow(double(ndx) / fullWhite, gamma1);
745  break;
746 
747  // kGammaMac <=> Rec 601 Gamma - SMPTE Range
749  // "gamma" (the exponent) = srcGamma / dstGamma
750  gamma1 = (inBank == kLUTBank_RGB2YUV ? (kGammaMac / 2.2) : (2.2 / kGammaMac) );
751  for (size_t ndx = 0; ndx < tableSize; ndx++)
752  {
753  if (ndx <= (uint32_t)smpteBlack || ndx >= (uint32_t)smpteWhite)
754  outTable[ndx] = double(ndx);
755  else
756  outTable[ndx] = smpteScale * ::pow((double(ndx) - smpteBlack) / smpteScale, gamma1) + smpteBlack;
757  }
758  break; // NTV2_LUTGamma18_Rec601_SMPTE
759 
760  // kGammaMac <=> Rec 709 Gamma - Full Range
762  if (inBank == kLUTBank_RGB2YUV)
763  {
764  gamma1 = kGammaMac;
765  gamma2 = 0.45;
766  for (size_t ndx = 0; ndx < tableSize; ndx++)
767  { // remove the kGammaMac power gamma
768  double f(::pow(double(ndx) / fullWhite, gamma1));
769 
770  // add the Rec 709 gamma
771  if (f < 0.018)
772  outTable[ndx] = fullWhite * (f * 4.5);
773  else
774  outTable[ndx] = fullWhite * ((1.099 * ::pow(f, gamma2)) - 0.099);
775  }
776  }
777  else
778  {
779  gamma1 = 1.0 / 0.45;
780  gamma2 = 1.0 / kGammaMac;
781  for (size_t ndx = 0; ndx < tableSize; ndx++)
782  {
783  double f(double(ndx) / fullWhite);
784  // remove the Rec 709 gamma
785  if (f < 0.081)
786  f = f / 4.5;
787  else
788  f = ::pow((f + 0.099) / 1.099, gamma1);
789 
790  // add the kGammaMac Power gamma
791  outTable[ndx] = fullWhite * ::pow(f, gamma2);
792  }
793  }
794  break; // NTV2_LUTGamma18_Rec709
795 
796  // kGammaMac <=> Rec 709 Gamma - SMPTE Range
798  if (inBank == kLUTBank_RGB2YUV)
799  {
800  gamma1 = kGammaMac;
801  gamma2 = 0.45;
802  for (size_t ndx = 0; ndx < tableSize; ndx++)
803  {
804  if (ndx <= (uint32_t)smpteBlack || ndx >= (uint32_t)smpteWhite)
805  outTable[ndx] = double(ndx); // linear portion - outside SMPTE range
806  else
807  { // remove the kGammaMac power gamma
808  double f(::pow((double(ndx) - smpteBlack) / 875.0, gamma1));
809 
810  // add the Rec 709 gamma
811  if (f < 0.018)
812  outTable[ndx] = smpteScale * (f * 4.5) + smpteBlack;
813  else
814  outTable[ndx] = smpteScale * ((1.099 * ::pow(f, gamma2)) - 0.099) + smpteBlack;
815  }
816  }
817  }
818  else
819  {
820  gamma1 = 1.0 / 0.45;
821  gamma2 = 1.0 / kGammaMac;
822  for (size_t ndx = 0; ndx < tableSize; ndx++)
823  {
824  if (ndx <= (uint32_t)smpteBlack || ndx >= (uint32_t)smpteWhite)
825  outTable[ndx] = double(ndx); // linear portion - outside SMPTE range
826  else
827  {
828  double f ((double(ndx) - smpteBlack) / 875.0);
829  // remove the Rec 709 gamma
830  if (f < 0.081)
831  f = f / 4.5;
832  else
833  f = ::pow((f + 0.099) / 1.099, gamma1);
834 
835  // add the kGammaMac Power gamma
836  outTable[ndx] = smpteScale * ::pow(f, gamma2) + smpteBlack;
837  }
838  }
839  }
840  break; // NTV2_LUTGamma18_Rec709_SMPTE
841  } // switch on inLUTType
842  return true;
843 } // GenerateGammaTable
844 
845 static inline ULWord intClamp (const int inMin, const int inValue, const int inMax)
846 {
847  return ULWord(inValue < inMin ? inMin : (inValue > inMax ? inMax : inValue));
848 }
849 
850 bool CNTV2Card::GenerateGammaTable (const NTV2LutType inLUTType, const int inBank, UWordSequence & outTable, const NTV2LutBitDepth inBitDepth)
851 {
852  NTV2DoubleArray dblTable;
853  size_t nonzeroes(0);
854  uint32_t tableSize = inBitDepth == NTV2_LUT10Bit ? 1024 : 4096;
855  if (!CNTV2Card::GenerateGammaTable (inLUTType, inBank, dblTable, inBitDepth))
856  return false;
857  if (dblTable.size() < tableSize)
858  return false;
859  outTable.reserve(tableSize);
860  while (outTable.size() < tableSize)
861  outTable.push_back(0);
862  for (size_t ndx(0); ndx < tableSize; ndx++)
863  {
864  if ((outTable.at(ndx) = UWord(intClamp(0, int(dblTable.at(ndx) + 0.5), tableSize-1))))
865  nonzeroes++;
866  }
867  if (nonzeroes >= tableSize)
868  {AJA_sWARNING(AJA_DebugUnit_LUT, AJAFUNC << ": " << DEC(nonzeroes) << " non-zero values -- at least " << DEC(tableSize-1)); return false;}
869  return nonzeroes >= tableSize;
870 }
871 
877 
878 static const size_t kLUTArraySize (NTV2_COLORCORRECTOR_WORDSPERTABLE * 2);
880 
881 
882 
883 // this allows for three 1024-entry LUTs that we're going to download to all four channels
884 bool CNTV2Card::DownloadLUTToHW (const NTV2DoubleArray & inRedLUT, const NTV2DoubleArray & inGreenLUT, const NTV2DoubleArray & inBlueLUT,
885  const NTV2Channel inLUT, const int inBank)
886 {
887  if (inRedLUT.size() < kLUTArraySize || inGreenLUT.size() < kLUTArraySize || inBlueLUT.size() < kLUTArraySize)
888  {LUTFAIL("Size error (< 1024): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
889 
890  if (IS_CHANNEL_INVALID(inLUT))
891  {LUTFAIL("Bad LUT/channel (> 7): " << DEC(inLUT)); return false;}
892 
893  if (inBank != 0 && inBank != 1)
894  {LUTFAIL("Bad bank value (> 1): " << DEC(inBank)); return false;}
895 
896  if (::NTV2DeviceGetNumLUTs(_boardID) == 0)
897  return true; // It's no sin to have been born with no LUTs
898 
899  bool bResult = SetLUTEnable(true, inLUT);
900  if (bResult)
901  {
902  // Set up Host Access...
903  bResult = SetColorCorrectionHostAccessBank (NTV2ColorCorrectionHostAccessBank (gLUTBank0[inLUT] + inBank));
904  if (bResult)
905  bResult = LoadLUTTables (inRedLUT, inGreenLUT, inBlueLUT);
906  SetLUTEnable (false, inLUT);
907  }
908  return bResult;
909 }
910 
911 bool CNTV2Card::Download12BitLUTToHW (const NTV2DoubleArray & inRedLUT, const NTV2DoubleArray & inGreenLUT, const NTV2DoubleArray & inBlueLUT,
912  const NTV2Channel inLUT, const int inBank)
913 {
914  if (inRedLUT.size() < k12BitLUTArraySize || inGreenLUT.size() < k12BitLUTArraySize || inBlueLUT.size() < k12BitLUTArraySize)
915  {LUTFAIL("Size error (< 4096): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
916 
917  if (IS_CHANNEL_INVALID(inLUT))
918  {LUTFAIL("Bad LUT/channel (> 7): " << DEC(inLUT)); return false;}
919 
920  if (inBank != 0 && inBank != 1)
921  {LUTFAIL("Bad bank value (> 1): " << DEC(inBank)); return false;}
922 
923  if (!Has12BitLUTSupport())
924  return false;
925 
926  if (::NTV2DeviceGetNumLUTs(_boardID) == 0)
927  return false;
928 
929  bool bResult = SetLUTEnable(true, inLUT);
930  if (bResult)
931  {
932  // Set up Host Access...
933  bResult = SetColorCorrectionHostAccessBank (NTV2ColorCorrectionHostAccessBank (gLUTBank0[inLUT] + inBank));
934  if (bResult)
935  bResult = Load12BitLUTTables (inRedLUT, inGreenLUT, inBlueLUT);
936  SetLUTEnable (false, inLUT);
937  }
938  return bResult;
939 }
940 
941 bool CNTV2Card::DownloadLUTToHW (const UWordSequence & inRedLUT, const UWordSequence & inGreenLUT, const UWordSequence & inBlueLUT,
942  const NTV2Channel inLUT, const int inBank)
943 {
944  if (inRedLUT.size() < kLUTArraySize || inGreenLUT.size() < kLUTArraySize || inBlueLUT.size() < kLUTArraySize)
945  {LUTFAIL("Size error (< 1024): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
946 
947  if (IS_CHANNEL_INVALID(inLUT))
948  {LUTFAIL("Bad LUT/channel (> 7): " << DEC(inLUT)); return false;}
949 
950  if (inBank != 0 && inBank != 1)
951  {LUTFAIL("Bad bank value (> 1): " << DEC(inBank)); return false;}
952 
953  if (::NTV2DeviceGetNumLUTs(_boardID) == 0)
954  return true; // It's no sin to have been born with no LUTs
955 
956  bool bResult = SetLUTEnable(true, inLUT);
957  if (bResult)
958  {
959  // Set up Host Access...
960  bResult = SetColorCorrectionHostAccessBank (NTV2ColorCorrectionHostAccessBank (gLUTBank0[inLUT] + inBank));
961  if (bResult)
962  bResult = WriteLUTTables (inRedLUT, inGreenLUT, inBlueLUT);
963  SetLUTEnable (false, inLUT);
964  }
965  return bResult;
966 }
967 
968 bool CNTV2Card::Download12BitLUTToHW (const UWordSequence & inRedLUT, const UWordSequence & inGreenLUT, const UWordSequence & inBlueLUT,
969  const NTV2Channel inLUT, const int inBank)
970 {
971  if (inRedLUT.size() < k12BitLUTArraySize || inGreenLUT.size() < k12BitLUTArraySize || inBlueLUT.size() < k12BitLUTArraySize)
972  {LUTFAIL("Size error (< 4096): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
973 
974  if (IS_CHANNEL_INVALID(inLUT))
975  {LUTFAIL("Bad LUT/channel (> 7): " << DEC(inLUT)); return false;}
976 
977  if (inBank != 0 && inBank != 1)
978  {LUTFAIL("Bad bank value (> 1): " << DEC(inBank)); return false;}
979 
980  if (!Has12BitLUTSupport())
981  return false;
982 
983  if (::NTV2DeviceGetNumLUTs(_boardID) == 0)
984  return false;
985 
986  bool bResult = SetLUTEnable(true, inLUT);
987  if (bResult)
988  {
989  // Set up Host Access...
990  bResult = SetColorCorrectionHostAccessBank (NTV2ColorCorrectionHostAccessBank (gLUTBank0[inLUT] + inBank));
991  if (bResult)
992  bResult = Write12BitLUTTables (inRedLUT, inGreenLUT, inBlueLUT);
993  SetLUTEnable (false, inLUT);
994  }
995  return bResult;
996 }
997 
998 bool CNTV2Card::LoadLUTTables (const NTV2DoubleArray & inRedLUT, const NTV2DoubleArray & inGreenLUT, const NTV2DoubleArray & inBlueLUT)
999 {
1000  if (inRedLUT.size() < kLUTArraySize || inGreenLUT.size() < kLUTArraySize || inBlueLUT.size() < kLUTArraySize)
1001  {LUTFAIL("Size error (< 1024): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
1002 
1003  UWordSequence redLUT, greenLUT, blueLUT;
1004  redLUT.resize(kLUTArraySize);
1005  greenLUT.resize(kLUTArraySize);
1006  blueLUT.resize(kLUTArraySize);
1007  for (size_t ndx(0); ndx < kLUTArraySize; ndx++)
1008  {
1009  redLUT .at(ndx) = UWord(intClamp(0, int(inRedLUT [ndx] + 0.5), 1023));
1010  greenLUT.at(ndx) = UWord(intClamp(0, int(inGreenLUT[ndx] + 0.5), 1023));
1011  blueLUT .at(ndx) = UWord(intClamp(0, int(inBlueLUT [ndx] + 0.5), 1023));
1012  }
1013  return WriteLUTTables(redLUT, greenLUT, blueLUT);
1014 }
1015 
1016 bool CNTV2Card::Load12BitLUTTables (const NTV2DoubleArray & inRedLUT, const NTV2DoubleArray & inGreenLUT, const NTV2DoubleArray & inBlueLUT)
1017 {
1018  if (inRedLUT.size() < k12BitLUTArraySize || inGreenLUT.size() < k12BitLUTArraySize || inBlueLUT.size() < k12BitLUTArraySize)
1019  {LUTFAIL("Size error (< 4096): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
1020 
1021  UWordSequence redLUT, greenLUT, blueLUT;
1022  redLUT.resize(k12BitLUTArraySize);
1023  greenLUT.resize(k12BitLUTArraySize);
1024  blueLUT.resize(k12BitLUTArraySize);
1025  for (size_t ndx(0); ndx < k12BitLUTArraySize; ndx++)
1026  {
1027  redLUT .at(ndx) = UWord(intClamp(0, int(inRedLUT [ndx] + 0.5), 4095));
1028  greenLUT.at(ndx) = UWord(intClamp(0, int(inGreenLUT[ndx] + 0.5), 4095));
1029  blueLUT .at(ndx) = UWord(intClamp(0, int(inBlueLUT [ndx] + 0.5), 4095));
1030  }
1031  return Write12BitLUTTables(redLUT, greenLUT, blueLUT);
1032 }
1033 
1034 bool CNTV2Card::WriteLUTTables (const UWordSequence & inRedLUT, const UWordSequence & inGreenLUT, const UWordSequence & inBlueLUT)
1035 {
1036  if (inRedLUT.size() < kLUTArraySize || inGreenLUT.size() < kLUTArraySize || inBlueLUT.size() < kLUTArraySize)
1037  {LUTFAIL("Size error (< 1024): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
1038 
1039  size_t errorCount(0), nonzeroes(0);
1040  ULWord RTableReg = (Has12BitLUTSupport() ? kColorCorrection12BitLUTOffset_Base : kColorCorrectionLUTOffset_Red) / 4; // Byte offset to LUT in register bar; divide by sizeof (ULWord) to get register number
1041  ULWord GTableReg = (Has12BitLUTSupport() ? kColorCorrection12BitLUTOffset_Base : kColorCorrectionLUTOffset_Green) / 4;
1042  ULWord BTableReg = (Has12BitLUTSupport() ? kColorCorrection12BitLUTOffset_Base : kColorCorrectionLUTOffset_Blue) / 4;
1043 
1044  for (size_t ndx(0); ndx < NTV2_COLORCORRECTOR_WORDSPERTABLE; ndx++)
1045  {
1046  ULWord loRed(ULWord(inRedLUT[2 * ndx + 0]) & 0x3FF);
1047  ULWord hiRed(ULWord(inRedLUT[2 * ndx + 1]) & 0x3FF);
1048 
1049  ULWord loGreen = ULWord(inGreenLUT[2 * ndx + 0]) & 0x3FF;
1050  ULWord hiGreen = ULWord(inGreenLUT[2 * ndx + 1]) & 0x3FF;
1051 
1052  ULWord loBlue = ULWord(inBlueLUT[2 * ndx + 0]) & 0x3FF;
1053  ULWord hiBlue = ULWord(inBlueLUT[2 * ndx + 1]) & 0x3FF;
1054 
1055  if(!Has12BitLUTSupport())
1056  {
1058  if (tmpRed) nonzeroes++;
1059  if (!WriteRegister(RTableReg++, tmpRed))
1060  errorCount++;
1061 
1062  ULWord tmpGreen = (hiGreen << kRegColorCorrectionLUTOddShift) + (loGreen << kRegColorCorrectionLUTEvenShift);
1063  if (tmpGreen) nonzeroes++;
1064  if (!WriteRegister(GTableReg++, tmpGreen))
1065  errorCount++;
1066 
1067  ULWord tmpBlue = (hiBlue << kRegColorCorrectionLUTOddShift) + (loBlue << kRegColorCorrectionLUTEvenShift);
1068  if (tmpBlue) nonzeroes++;
1069  if (!WriteRegister(BTableReg++, tmpBlue))
1070  errorCount++;
1071  }
1072  else
1073  {
1076  if(tmpRedLo || tmpRedHi) nonzeroes++;
1077  Set12BitLUTPlaneSelect(NTV2_REDPLANE);
1078  if (!WriteRegister(RTableReg++, tmpRedLo))
1079  errorCount++;
1080  if (!WriteRegister(RTableReg++, tmpRedLo))
1081  errorCount++;
1082  if (!WriteRegister(RTableReg++, tmpRedHi))
1083  errorCount++;
1084  if (!WriteRegister(RTableReg++, tmpRedHi))
1085  errorCount++;
1086 
1089  if(tmpGreenLo || tmpGreenHi) nonzeroes++;
1090  Set12BitLUTPlaneSelect(NTV2_GREENPLANE);
1091  if (!WriteRegister(GTableReg++, tmpGreenLo))
1092  errorCount++;
1093  if (!WriteRegister(GTableReg++, tmpGreenLo))
1094  errorCount++;
1095  if (!WriteRegister(GTableReg++, tmpGreenHi))
1096  errorCount++;
1097  if (!WriteRegister(GTableReg++, tmpGreenHi))
1098  errorCount++;
1099 
1102  if(tmpBlueLo || tmpBlueHi) nonzeroes++;
1103  Set12BitLUTPlaneSelect(NTV2_BLUEPLANE);
1104  if (!WriteRegister(BTableReg++, tmpBlueLo))
1105  errorCount++;
1106  if (!WriteRegister(BTableReg++, tmpBlueLo))
1107  errorCount++;
1108  if (!WriteRegister(BTableReg++, tmpBlueHi))
1109  errorCount++;
1110  if (!WriteRegister(BTableReg++, tmpBlueHi))
1111  errorCount++;
1112  }
1113  }
1114  if (errorCount) LUTFAIL(GetDisplayName() << " " << DEC(errorCount) << " WriteRegister calls failed");
1115  else if (!nonzeroes) LUTWARN(GetDisplayName() << " All zero LUT table values!");
1116  return !errorCount;
1117 }
1118 
1119 bool CNTV2Card::Write12BitLUTTables (const UWordSequence & inRedLUT, const UWordSequence & inGreenLUT, const UWordSequence & inBlueLUT)
1120 {
1121  if (inRedLUT.size() < k12BitLUTArraySize || inGreenLUT.size() < k12BitLUTArraySize || inBlueLUT.size() < k12BitLUTArraySize)
1122  {LUTFAIL("Size error (< 4096): R=" << DEC(inRedLUT.size()) << " G=" << DEC(inGreenLUT.size()) << " B=" << DEC(inBlueLUT.size())); return false;}
1123 
1124  if (!Has12BitLUTSupport())
1125  return false;
1126 
1127  size_t errorCount(0), nonzeroes(0);
1128  ULWord RTableReg(kColorCorrection12BitLUTOffset_Base / 4); // Byte offset to LUT in register bar; divide by sizeof (ULWord) to get register number
1131 
1132  Set12BitLUTPlaneSelect(NTV2_REDPLANE);
1133  for (size_t ndx(0); ndx < NTV2_12BIT_COLORCORRECTOR_WORDSPERTABLE; ndx++)
1134  {
1135  ULWord loRed(ULWord(inRedLUT[2 * ndx + 0]) & 0xFFF);
1136  ULWord hiRed(ULWord(inRedLUT[2 * ndx + 1]) & 0xFFF);
1137 
1139  if (tmpRed) nonzeroes++;
1140  if (!WriteRegister(RTableReg++, tmpRed))
1141  errorCount++;
1142  }
1143 
1144  Set12BitLUTPlaneSelect(NTV2_GREENPLANE);
1145  for (size_t ndx(0); ndx < NTV2_12BIT_COLORCORRECTOR_WORDSPERTABLE; ndx++)
1146  {
1147  ULWord loGreen = ULWord(inGreenLUT[2 * ndx + 0]) & 0xFFF;
1148  ULWord hiGreen = ULWord(inGreenLUT[2 * ndx + 1]) & 0xFFF;
1149 
1151  if (tmpGreen) nonzeroes++;
1152  if (!WriteRegister(GTableReg++, tmpGreen))
1153  errorCount++;
1154  }
1155 
1156  Set12BitLUTPlaneSelect(NTV2_BLUEPLANE);
1157  for (size_t ndx(0); ndx < NTV2_12BIT_COLORCORRECTOR_WORDSPERTABLE; ndx++)
1158  {
1159  ULWord loBlue = ULWord(inBlueLUT[2 * ndx + 0]) & 0xFFF;
1160  ULWord hiBlue = ULWord(inBlueLUT[2 * ndx + 1]) & 0xFFF;
1161 
1163  if (tmpBlue) nonzeroes++;
1164  if (!WriteRegister(BTableReg++, tmpBlue))
1165  errorCount++;
1166  }
1167 
1168  if (errorCount) LUTFAIL(GetDisplayName() << " " << DEC(errorCount) << " WriteRegister calls failed");
1169  else if (!nonzeroes) LUTWARN(GetDisplayName() << " All zero LUT table values!");
1170  return !errorCount;
1171 }
1172 
1173 bool CNTV2Card::GetLUTTables (NTV2DoubleArray & outRedLUT, NTV2DoubleArray & outGreenLUT, NTV2DoubleArray & outBlueLUT)
1174 {
1175  outRedLUT.clear(); outRedLUT.resize (kLUTArraySize);
1176  outGreenLUT.clear(); outGreenLUT.resize(kLUTArraySize);
1177  outBlueLUT.clear(); outBlueLUT.resize(kLUTArraySize);
1178 
1179  UWordSequence red, green, blue;
1180  if (!ReadLUTTables(red, green, blue))
1181  return false;
1182  if (red.size() != green.size() || green.size() != blue.size())
1183  {LUTFAIL("Unexpected size mismatch: R(" << DEC(red.size()) << ")!=G(" << DEC(green.size()) << ")!=B(" << DEC(blue.size()) << ")"); return false;}
1184  if (red.size() != outRedLUT.size() || green.size() != outGreenLUT.size() || blue.size() != outBlueLUT.size())
1185  {LUTFAIL("Unexpected size mismatch: R(" << DEC(red.size()) << ")!=oR(" << DEC(outRedLUT.size())
1186  << ") G(" << DEC(green.size()) << ")!=oG(" << DEC(outGreenLUT.size())
1187  << ") B(" << DEC(blue.size()) << ")!=oB(" << DEC(outBlueLUT.size())
1188  << ")"); return false;}
1189 
1190  for (size_t ndx(0); ndx < kLUTArraySize; ndx++)
1191  {
1192  outRedLUT [ndx] = red[ndx];
1193  outGreenLUT[ndx] = green[ndx];
1194  outBlueLUT [ndx] = blue[ndx];
1195  }
1196  return true;
1197 }
1198 
1199 bool CNTV2Card::Get12BitLUTTables (NTV2DoubleArray & outRedLUT, NTV2DoubleArray & outGreenLUT, NTV2DoubleArray & outBlueLUT)
1200 {
1201  outRedLUT.clear(); outRedLUT.resize (k12BitLUTArraySize);
1202  outGreenLUT.clear(); outGreenLUT.resize(k12BitLUTArraySize);
1203  outBlueLUT.clear(); outBlueLUT.resize(k12BitLUTArraySize);
1204 
1205  if(!Has12BitLUTSupport())
1206  return false;
1207 
1208  UWordSequence red, green, blue;
1209  if (!Read12BitLUTTables(red, green, blue))
1210  return false;
1211  if (red.size() != green.size() || green.size() != blue.size())
1212  {LUTFAIL("Unexpected size mismatch: R(" << DEC(red.size()) << ")!=G(" << DEC(green.size()) << ")!=B(" << DEC(blue.size()) << ")"); return false;}
1213  if (red.size() != outRedLUT.size() || green.size() != outGreenLUT.size() || blue.size() != outBlueLUT.size())
1214  {LUTFAIL("Unexpected size mismatch: R(" << DEC(red.size()) << ")!=oR(" << DEC(outRedLUT.size())
1215  << ") G(" << DEC(green.size()) << ")!=oG(" << DEC(outGreenLUT.size())
1216  << ") B(" << DEC(blue.size()) << ")!=oB(" << DEC(outBlueLUT.size())
1217  << ")"); return false;}
1218 
1219  for (size_t ndx(0); ndx < k12BitLUTArraySize; ndx++)
1220  {
1221  outRedLUT [ndx] = red[ndx];
1222  outGreenLUT[ndx] = green[ndx];
1223  outBlueLUT [ndx] = blue[ndx];
1224  }
1225  return true;
1226 }
1227 
1228 bool CNTV2Card::ReadLUTTables (UWordSequence & outRedLUT, UWordSequence & outGreenLUT, UWordSequence & outBlueLUT)
1229 {
1230  ULWord RTableReg (kColorCorrectionLUTOffset_Red / 4); // Byte offset to LUT in register bar; divide by sizeof (ULWord) to get register number
1231  ULWord GTableReg (kColorCorrectionLUTOffset_Green / 4);
1232  ULWord BTableReg (kColorCorrectionLUTOffset_Blue / 4);
1233  size_t errors(0), nonzeroes(0);
1234 
1235  outRedLUT.clear(); outRedLUT.resize(kLUTArraySize);
1236  outGreenLUT.clear(); outGreenLUT.resize(kLUTArraySize);
1237  outBlueLUT.clear(); outBlueLUT.resize(kLUTArraySize);
1238 
1239  for (size_t ndx(0); ndx < kLUTArraySize; ndx += 2)
1240  {
1241  ULWord temp(0);
1242  if (!ReadRegister(RTableReg++, temp))
1243  errors++;
1244  outRedLUT[ndx + 0] = (temp >> kRegColorCorrectionLUTEvenShift) & 0x3FF;
1245  outRedLUT[ndx + 1] = (temp >> kRegColorCorrectionLUTOddShift ) & 0x3FF;
1246  if (temp) nonzeroes++;
1247 
1248  if (!ReadRegister(GTableReg++, temp))
1249  errors++;
1250  outGreenLUT[ndx + 0] = (temp >> kRegColorCorrectionLUTEvenShift) & 0x3FF;
1251  outGreenLUT[ndx + 1] = (temp >> kRegColorCorrectionLUTOddShift ) & 0x3FF;
1252  if (temp) nonzeroes++;
1253 
1254  if (!ReadRegister(BTableReg++, temp))
1255  errors++;
1256  outBlueLUT[ndx + 0] = (temp >> kRegColorCorrectionLUTEvenShift) & 0x3FF;
1257  outBlueLUT[ndx + 1] = (temp >> kRegColorCorrectionLUTOddShift ) & 0x3FF;
1258  if (temp) nonzeroes++;
1259  }
1260  if (errors) LUTFAIL(GetDisplayName() << " " << DEC(errors) << " ReadRegister calls failed");
1261  else if (!nonzeroes) LUTWARN(GetDisplayName() << " All zero LUT table values!");
1262  return !errors;
1263 }
1264 
1265 bool CNTV2Card::Read12BitLUTTables (UWordSequence & outRedLUT, UWordSequence & outGreenLUT, UWordSequence & outBlueLUT)
1266 {
1267  ULWord RTableReg (kColorCorrection12BitLUTOffset_Base / 4); // Byte offset to LUT in register bar; divide by sizeof (ULWord) to get register number
1270  size_t errors(0), nonzeroes(0);
1271 
1272  if(!Has12BitLUTSupport())
1273  return false;
1274 
1275  outRedLUT.clear(); outRedLUT.resize(k12BitLUTArraySize);
1276  outGreenLUT.clear(); outGreenLUT.resize(k12BitLUTArraySize);
1277  outBlueLUT.clear(); outBlueLUT.resize(k12BitLUTArraySize);
1278 
1279  Set12BitLUTPlaneSelect(NTV2_REDPLANE);
1280  for (size_t ndx(0); ndx < k12BitLUTArraySize; ndx += 2)
1281  {
1282  ULWord temp(0);
1283  if (!ReadRegister(RTableReg++, temp))
1284  errors++;
1285  outRedLUT[ndx + 0] = (temp >> kRegColorCorrection12BitLUTEvenShift) & 0xFFF;
1286  outRedLUT[ndx + 1] = (temp >> kRegColorCorrection12BitLUTOddShift ) & 0xFFF;
1287  if (temp) nonzeroes++;
1288  }
1289 
1290  Set12BitLUTPlaneSelect(NTV2_GREENPLANE);
1291  for (size_t ndx(0); ndx < k12BitLUTArraySize; ndx += 2)
1292  {
1293  ULWord temp(0);
1294  if (!ReadRegister(GTableReg++, temp))
1295  errors++;
1296  outGreenLUT[ndx + 0] = (temp >> kRegColorCorrection12BitLUTEvenShift) & 0xFFF;
1297  outGreenLUT[ndx + 1] = (temp >> kRegColorCorrection12BitLUTOddShift ) & 0xFFF;
1298  if (temp) nonzeroes++;
1299  }
1300 
1301  Set12BitLUTPlaneSelect(NTV2_BLUEPLANE);
1302  for (size_t ndx(0); ndx < k12BitLUTArraySize; ndx += 2)
1303  {
1304  ULWord temp(0);
1305  if (!ReadRegister(BTableReg++, temp))
1306  errors++;
1307  outBlueLUT[ndx + 0] = (temp >> kRegColorCorrection12BitLUTEvenShift) & 0xFFF;
1308  outBlueLUT[ndx + 1] = (temp >> kRegColorCorrection12BitLUTOddShift ) & 0xFFF;
1309  if (temp) nonzeroes++;
1310  }
1311 
1312  if (errors) LUTFAIL(GetDisplayName() << " " << DEC(errors) << " ReadRegister calls failed");
1313  else if (!nonzeroes) LUTWARN(GetDisplayName() << " All zero LUT table values!");
1314  return !errors;
1315 }
1316 
1317 bool CNTV2Card::SetLUTEnable (const bool inEnable, const NTV2Channel inLUT)
1318 {
1323  static const UWord BitCountNibble[] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4};
1324  ULWord supported = 0;
1325 
1326  if (IS_CHANNEL_INVALID(inLUT))
1327  {LUTFAIL("Bad LUT number (> 7): " << DEC(inLUT)); return false;}
1328  if (GetNumSupported(kDeviceGetLUTVersion) < 2)
1329  return true; // LUT init not needed
1330  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
1331  {
1332  if (GetIndexForNTV2Channel(inLUT) >= GetNumSupported(kDeviceGetNumLUTs))
1333  return false;
1334  if (!ReadRegister(gChannelCapabilities[inLUT], supported, maskCCLUTV3HostLoad, shiftCCLUTV3HostLoad) || (supported == 0))
1335  return false;
1336  if (!WriteRegister(gChannelHostLoad[inLUT], inEnable, maskCCLUTV3LoadEnable, shiftCCLUTV3LoadEnable))
1337  return false;
1338  }
1339  else
1340  {
1341  // Sanity check...
1342  const ULWord mask(LUTEnableMasks[inLUT]), shift(LUTEnableShifts[inLUT]); ULWord tmp(0);
1343  if (ReadRegister(kRegLUTV2Control, tmp))
1344  if (((tmp & mask)?true:false) == inEnable)
1345  LUTWARN(GetDisplayName() << " V2 LUT" << DEC(inLUT+1) << " Enable bit already " << (inEnable?"set":"clear"));
1346  tmp &= 0x000000FF;
1347  if (inEnable)
1348  if (BitCountNibble[tmp & 0xF] || BitCountNibble[(tmp >> 4) & 0xF])
1349  LUTWARN(GetDisplayName() << " Setting V2 LUT" << DEC(inLUT+1) << " Enable bit: multiple Enable bits set: " << xHEX0N(tmp,4));
1350 
1351  // Set or Clear the Enable bit...
1352  if (!WriteRegister (kRegLUTV2Control, inEnable ? 1 : 0, mask, shift))
1353  {LUTFAIL(GetDisplayName() << " WriteRegister kRegLUTV2Control failed, enable=" << DEC(UWord(inEnable))); return false;}
1354 
1355  // Sanity check...
1356  if (!inEnable)
1357  if (ReadRegister(kRegLUTV2Control, tmp, 0x000000FF)) // all enable masks
1358  if (tmp)
1359  LUTWARN(GetDisplayName() << " Clearing V2 LUT" << DEC(inLUT+1) << " Enable bit: still has Enable bit(s) set: " << xHEX0N(tmp,4));
1360  }
1361 
1362  return true;
1363 }
1364 
1365 
1367 {
1368  if (IS_CHANNEL_INVALID (inChannel))
1369  return false;
1370  if (!NTV2_IS_VALID_CSCRGBRANGE(inRange))
1371  return false;
1372  return WriteRegister (gChannelToCSCoeff34RegNum[inChannel], inRange, kK2RegMaskXena2RGBRange, kK2RegShiftXena2RGBRange);
1373 }
1374 
1376 {
1377  outRange = NTV2_CSC_RGB_RANGE_INVALID;
1378  if (IS_CHANNEL_INVALID (inChannel))
1379  return false;
1380  ULWord regValue (0);
1381  if (!ReadRegister (gChannelToCSCoeff34RegNum[inChannel], regValue, kK2RegMaskXena2RGBRange, kK2RegShiftXena2RGBRange))
1382  return false;
1383  outRange = NTV2_CSC_RGB_Range(regValue);
1384  return true;
1385 }
1386 
1387 bool CNTV2Card::SetColorSpaceUseCustomCoefficient (ULWord useCustomCoefficient, const NTV2Channel inChannel)
1388 {
1389  if (IS_CHANNEL_INVALID (inChannel))
1390  return false;
1391  return WriteRegister (gChannelToCSCoeff12RegNum [inChannel], useCustomCoefficient, kK2RegMaskUseCustomCoefSelect, kK2RegShiftUseCustomCoefSelect);
1392 }
1393 
1394 bool CNTV2Card::GetColorSpaceUseCustomCoefficient (ULWord & outUseCustomCoefficient, const NTV2Channel inChannel)
1395 {
1396  return !IS_CHANNEL_INVALID(inChannel)
1397  && ReadRegister (gChannelToCSCoeff12RegNum[inChannel], outUseCustomCoefficient, kK2RegMaskUseCustomCoefSelect, kK2RegShiftUseCustomCoefSelect);
1398 }
1399 
1400 bool CNTV2Card::SetColorSpaceMakeAlphaFromKey (const bool inMakeAlphaFromKey, const NTV2Channel inChannel)
1401 {
1402  return !IS_CHANNEL_INVALID(inChannel)
1403  && WriteRegister (gChannelToCSCoeff12RegNum[inChannel], inMakeAlphaFromKey?1:0, kK2RegMaskMakeAlphaFromKeySelect, kK2RegShiftMakeAlphaFromKeySelect);
1404 }
1405 
1406 bool CNTV2Card::GetColorSpaceMakeAlphaFromKey (ULWord & outMakeAlphaFromKey, const NTV2Channel inChannel)
1407 {
1408  return !IS_CHANNEL_INVALID(inChannel)
1409  && ReadRegister (gChannelToCSCoeff12RegNum[inChannel], outMakeAlphaFromKey, kK2RegMaskMakeAlphaFromKeySelect, kK2RegShiftMakeAlphaFromKeySelect);
1410 }
1411 
1413 {
1414  if (IS_CHANNEL_INVALID(inChannel))
1415  return false;
1416 
1427 }
1428 
1430 {
1431  if (IS_CHANNEL_INVALID (inChannel))
1432  return false;
1433 
1444 }
1445 
1446 // 12/7/2006 To increase accuracy and decrease generational degredation, the width of the coefficients
1447 // for the colorspace converter matrix went from 10 to 12 bit (with the MSB being a sign
1448 // bit). So as not to break existing, compiled code, we added new API calls for use with
1449 // these wider coefficients. The values had to be munged a bit to fit in the register, since
1450 // the low coefficient ended on the 0 bit ... the hi coefficient was simply widened to 13 bits
1451 // total. The 2 LSBs of the low coefficient are written *in front* of the 11 MSBs, hence the
1452 // shifting and masking below. - jac
1454 {
1455  if (IS_CHANNEL_INVALID (inChannel))
1456  return false;
1457 
1458  ULWord MSBs(inCoefficients.Coefficient1 >> 2);
1459  ULWord LSBs(inCoefficients.Coefficient1 & 0x00000003);
1460  if (!WriteRegister (gChannelToCSCoeff12RegNum[inChannel], MSBs | (LSBs << 11), kK2RegMaskCustomCoefficient12BitLow, kK2RegShiftCustomCoefficient12BitLow)
1462  return false;
1463 
1464  MSBs = inCoefficients.Coefficient3 >> 2;
1465  LSBs = inCoefficients.Coefficient3 & 0x00000003;
1466  if (!WriteRegister (gChannelToCSCoeff34RegNum[inChannel], MSBs | (LSBs << 11), kK2RegMaskCustomCoefficient12BitLow, kK2RegShiftCustomCoefficient12BitLow)
1468  return false;
1469 
1470  MSBs = inCoefficients.Coefficient5 >> 2;
1471  LSBs = inCoefficients.Coefficient5 & 0x00000003;
1472  if (!WriteRegister (gChannelToCSCoeff56RegNum[inChannel], MSBs | (LSBs << 11), kK2RegMaskCustomCoefficient12BitLow, kK2RegShiftCustomCoefficient12BitLow)
1474  return false;
1475 
1476  MSBs = inCoefficients.Coefficient7 >> 2;
1477  LSBs = inCoefficients.Coefficient7 & 0x00000003;
1478  if (!WriteRegister (gChannelToCSCoeff78RegNum[inChannel], MSBs | (LSBs << 11), kK2RegMaskCustomCoefficient12BitLow, kK2RegShiftCustomCoefficient12BitLow)
1480  return false;
1481 
1482  MSBs = inCoefficients.Coefficient9 >> 2;
1483  LSBs = inCoefficients.Coefficient9 & 0x00000003;
1484  return WriteRegister (gChannelToCSCoeff910RegNum[inChannel], MSBs | (LSBs << 11), kK2RegMaskCustomCoefficient12BitLow, kK2RegShiftCustomCoefficient12BitLow)
1486 }
1487 
1488 // 12/7/2006 To increase accuracy and decrease generational degredation, the width of the coefficients
1489 // for the colorspace converter matrix went from 10 to 12 bit (with the MSB being a sign
1490 // bit). So as not to break existing, compiled code, we added new API calls for use with
1491 // these wider coefficients. The values had to be munged a bit to fit in the register, since
1492 // the low coefficient ended on the 0 bit ... the hi coefficient was simply widened to 13 bits
1493 // total. The 2 LSBs of the low coefficient are written *in front* of the 11 MSBs, hence the
1494 // shifting and masking below. - jac
1496 {
1497  if (IS_CHANNEL_INVALID (inChannel))
1498  return false;
1499 
1500  ULWord regVal(0), MSBs(0), LSBs(0);
1501 
1503  return false;
1504  LSBs = (regVal >> 11) & 0x00000003;
1505  MSBs = regVal & 0x000007FF;
1506  outCoefficients.Coefficient1 = MSBs | LSBs;
1507 
1510  return false;
1511  LSBs = (regVal >> 11) & 0x00000003;
1512  MSBs = regVal & 0x000007FF;
1513  outCoefficients.Coefficient3 = MSBs | LSBs;
1514 
1517  return false;
1518  LSBs = (regVal >> 11) & 0x00000003;
1519  MSBs = regVal & 0x000007FF;
1520  outCoefficients.Coefficient5 = MSBs | LSBs;
1521 
1524  return false;
1525  LSBs = (regVal >> 11) & 0x00000003;
1526  MSBs = regVal & 0x000007FF;
1527  outCoefficients.Coefficient7 = MSBs | LSBs;
1528 
1531  return false;
1532  LSBs = (regVal >> 11) & 0x00000003;
1533  MSBs = regVal & 0x000007FF;
1534  outCoefficients.Coefficient9 = MSBs | LSBs;
1536 }
1537 
1538 
1539 bool CNTV2Card::GetColorSpaceVideoKeySyncFail (bool & outVideoKeySyncFail, const NTV2Channel inChannel)
1540 {
1541  ULWord value(0);
1542  const bool status (!IS_CHANNEL_INVALID(inChannel) && ReadRegister(gChannelToCSCoeff12RegNum[inChannel], value, kK2RegMaskVidKeySyncStatus, kK2RegShiftVidKeySyncStatus));
1543  outVideoKeySyncFail = (value == 1);
1544  return status;
1545 }
1546 
1548 
1549 
1550 bool CNTV2Card::GenerateGammaTable (const NTV2LutType inLUTType, const int inBank, double * pOutTable)
1551 {
1552  if (!pOutTable)
1553  return false;
1554  NTV2DoubleArray table;
1555  if (!GenerateGammaTable(inLUTType, inBank, table))
1556  return false;
1557  ::memcpy(pOutTable, &table[0], table.size() * sizeof(double));
1558  return true;
1559 }
1560 
1561 // this assumes we have one 1024-entry LUT that we're going to download to all four channels
1562 bool CNTV2Card::DownloadLUTToHW (const double * pInTable, const NTV2Channel inChannel, const int inBank)
1563 {
1564  if (IS_CHANNEL_INVALID (inChannel))
1565  return false; // Invalid channel
1566 
1567  if (!pInTable)
1568  return false; // NULL table pointer
1569 
1570  if (inBank != 0 && inBank != 1)
1571  return false; // Bad bank value (must be 0 or 1)
1572 
1573  if (::NTV2DeviceGetNumLUTs (_boardID) == 0)
1574  return true; // It's no sin to have been born without any LUTs
1575 
1576  bool bResult = SetLUTEnable (true, inChannel);
1577  if (bResult)
1578  {
1579  // Set up Host Access...
1580  bResult = SetColorCorrectionHostAccessBank (NTV2ColorCorrectionHostAccessBank (gLUTBank0 [inChannel] + inBank));
1581  if (bResult)
1582  bResult = LoadLUTTable (pInTable);
1583  SetLUTEnable (false, inChannel);
1584  }
1585  return bResult;
1586 }
1587 
1588 
1589 bool CNTV2Card::LoadLUTTable (const double * pInTable)
1590 {
1591  if (!pInTable)
1592  return false;
1593 
1594  // Hope and pray that the caller's array has at least 1024 elements...
1595  NTV2DoubleArray rgbLUT;
1596  for (size_t ndx(0); ndx < kLUTArraySize; ndx++)
1597  rgbLUT.push_back(pInTable[ndx]);
1598 
1599  // Call the function that accepts NTV2DoubleArrays...
1600  return LoadLUTTables(rgbLUT, rgbLUT, rgbLUT);
1601 }
1602 
1603 bool CNTV2Card::Set3DLUTTableLocation (const ULWord inFrameNumber, ULWord inLUTIndex)
1604 {
1605  ULWord LUTTableIndexOffset = LUTTablePartitionSize * inLUTIndex;
1606  NTV2Framesize hwFrameSize;
1607  GetFrameBufferSize(NTV2_CHANNEL1, hwFrameSize);
1608  ULWord actualFrameSize (::NTV2FramesizeToByteCount(hwFrameSize));
1609  bool quadEnabled(false), quadQuadEnabled(false);
1610  GetQuadFrameEnable(quadEnabled, NTV2_CHANNEL1);
1611  GetQuadQuadFrameEnable(quadQuadEnabled, NTV2_CHANNEL1);
1612  if (quadEnabled)
1613  actualFrameSize *= 4;
1614  if (quadQuadEnabled)
1615  actualFrameSize *= 4;
1616  ULWord lutTableLocation (((actualFrameSize * inFrameNumber)/4) + LUTTableIndexOffset/4);
1617  return WriteRegister(kReg3DLUTLoadControl, lutTableLocation, 0x3FFFFFFF, 0);
1618 }
1619 
1621 {
1622  WriteRegister(kReg3DLUTLoadControl, 0, 0x80000000, 31);
1623  return WriteRegister(kReg3DLUTLoadControl, 1, 0x80000000, 31);
1624 }
1625 
1626 bool CNTV2Card::Set1DLUTTableLocation (const NTV2Channel inChannel, const ULWord inFrameNumber, ULWord inLUTIndex)
1627 {
1628  ULWord LUTTableIndexOffset = LUTTablePartitionSize * inLUTIndex;
1629  NTV2Framesize hwFrameSize;
1630  GetFrameBufferSize(NTV2_CHANNEL1, hwFrameSize);
1631  ULWord actualFrameSize (::NTV2FramesizeToByteCount(hwFrameSize));
1632  bool quadEnabled(false), quadQuadEnabled(false);
1633  GetQuadFrameEnable(quadEnabled, NTV2_CHANNEL1);
1634  GetQuadQuadFrameEnable(quadQuadEnabled, NTV2_CHANNEL1);
1635  if (quadEnabled)
1636  actualFrameSize *= 4;
1637  if (quadQuadEnabled)
1638  actualFrameSize *= 4;
1639  ULWord lutTableLocation (((actualFrameSize * inFrameNumber)/4) + LUTTableIndexOffset/4);
1640 
1641  ULWord supported = 0;
1642  bool result = false;
1643  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
1644  {
1645  if (GetIndexForNTV2Channel(inChannel) >= GetNumSupported(kDeviceGetNumLUTs))
1646  return false;
1647  if (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3DmaLoad, shiftCCLUTV3DmaLoad) || (supported == 0))
1648  return false;
1649  if (!WriteRegister(gChannelDmaLoad[inChannel], lutTableLocation, maskCCLUTV3Address, shiftCCLUTV3Address))
1650  return false;
1651  }
1652  else
1653  {
1654  result = WriteRegister(gChannelTo1DLutControlRegNum[inChannel], lutTableLocation, kRegMaskLUTAddress, kRegShiftLUTAddress);
1655  }
1656  return result;
1657 }
1658 
1660 {
1661  ULWord supported = 0;
1662  bool result = false;
1663  if (GetNumSupported(kDeviceGetLUTVersion) == 3)
1664  {
1665  if (GetIndexForNTV2Channel(inChannel) >= GetNumSupported(kDeviceGetNumLUTs))
1666  return false;
1667  if (!ReadRegister(gChannelCapabilities[inChannel], supported, maskCCLUTV3DmaLoad, shiftCCLUTV3DmaLoad) || (supported == 0))
1668  return false;
1669  if (!WriteRegister(gChannelDmaLoad[inChannel], 0, maskCCLUTV3Load, shiftCCLUTV3Load))
1670  return false;
1671  result = WriteRegister(gChannelDmaLoad[inChannel], 1, maskCCLUTV3Load, shiftCCLUTV3Load);
1672  }
1673  else
1674  {
1675  if (!WriteRegister(gChannelTo1DLutControlRegNum[inChannel], 0, static_cast<ULWord>(kRegMaskLUTLoad), kRegShiftLUTLoad))
1676  return false;
1677  result = WriteRegister(gChannelTo1DLutControlRegNum[inChannel], 1, static_cast<ULWord>(kRegMaskLUTLoad), kRegShiftLUTLoad);
1678  }
1679  return result;
1680 }
1681 
1682 
1684 
1685 #ifdef MSWindows
1686 #pragma warning(default: 4800)
1687 #endif
#define kRegColorCorrection10To12BitLUTOddShift
#define kRegColorCorrection12BitLUTEvenShift
virtual bool GetColorSpaceCustomCoefficients12Bit(NTV2CSCCustomCoeffs &outCustomCoefficients, const NTV2Channel inChannel=NTV2_CHANNEL1)
virtual bool SetColorCorrectionMode(const NTV2Channel inChannel, const NTV2ColorCorrectionMode inMode)
Definition: ntv2csclut.cpp:100
static const ULWord gChannelToCSCoeff910RegNum[]
Definition: ntv2csclut.cpp:58
#define NTV2_IS_VALID_CSCRGBRANGE(__v__)
Definition: ntv2enums.h:3771
static const NTV2ColorCorrectionHostAccessBank gLUTBank0[]
Definition: ntv2csclut.cpp:872
NTV2LutBitDepth
This specifies the LUT bit depth.
Definition: ntv2enums.h:3583
static const ULWord gChannelToCSCoeff12RegNum[]
Definition: ntv2csclut.cpp:46
#define kRegColorCorrectionLUTOddShift
virtual bool Download12BitLUTToHW(const NTV2DoubleArray &inRedLUT, const NTV2DoubleArray &inGreenLUT, const NTV2DoubleArray &inBlueLUT, const NTV2Channel inLUT, const int inBank)
Definition: ntv2csclut.cpp:911
virtual bool GetColorSpaceRGBBlackRange(NTV2_CSC_RGB_Range &outRange, const NTV2Channel inChannel=NTV2_CHANNEL1)
Answers with the current RGB range being used by a given CSC.
virtual bool Set3DLUTTableLocation(const ULWord inFrameNumber, ULWord inLUTIndex=0)
virtual bool GetColorSpaceVideoKeySyncFail(bool &outVideoKeySyncFail, const NTV2Channel inChannel=NTV2_CHANNEL1)
Answers whether or not the video signal present at the CSC’s Key Input is in sync with the video sig...
virtual bool Set12BitLUTPlaneSelect(const NTV2LUTPlaneSelect inLUTPlane, const NTV2Channel inChannel=NTV2_MAX_NUM_CHANNELS)
Sets the LUT plane.
Definition: ntv2csclut.cpp:487
virtual bool SetColorCorrectionSaturation(const NTV2Channel inChannel, const ULWord inValue)
Definition: ntv2csclut.cpp:438
std::vector< double > NTV2DoubleArray
An array of double-precision floating-point values.
virtual bool GetLUTV3OutputBank(const NTV2Channel inLUTWidget, ULWord &outBank)
Definition: ntv2csclut.cpp:208
static const ULWord gChannelToCSCoeff78RegNum[]
Definition: ntv2csclut.cpp:55
virtual bool SetColorSpaceCustomCoefficients12Bit(const NTV2CSCCustomCoeffs &inCustomCoefficients, const NTV2Channel inChannel=NTV2_CHANNEL1)
#define kRegColorCorrectionLUTEvenShift
#define AJA_sWARNING(_index_, _expr_)
Definition: debug.h:187
virtual bool GetColorSpaceMatrixSelect(NTV2ColorSpaceMatrixType &outType, const NTV2Channel inChannel=NTV2_CHANNEL1)
Answers with the current matrix type being used for the given CSC.
Definition: ntv2csclut.cpp:649
Declares the AJADebug class.
virtual bool SetColorSpaceMethod(const NTV2ColorSpaceMethod inCSCMethod, const NTV2Channel inChannel)
Selects the color space converter operation method.
Definition: ntv2csclut.cpp:553
#define LUTFAIL(__x__)
Definition: ntv2csclut.cpp:30
#define AJAFUNC
Definition: ajatypes.h:293
#define kLUTBank_RGB2YUV
Definition: ntv2enums.h:3555
#define kColorCorrectionLUTOffset_Green
ULWord GetIndexForNTV2Channel(const NTV2Channel inChannel)
Definition: ntv2utils.cpp:4702
static const ULWord gChannelToCSCoeff56RegNum[]
Definition: ntv2csclut.cpp:52
#define kColorCorrectionLUTOffset_Blue
bool NTV2DeviceCanDoEnhancedCSC(const NTV2DeviceID inDeviceID)
virtual bool Get12BitLUTPlaneSelect(NTV2LUTPlaneSelect &outLUTPlane, const NTV2Channel inChannel=NTV2_MAX_NUM_CHANNELS)
Answers with the current LUT plane.
Definition: ntv2csclut.cpp:523
virtual bool LoadLUTTables(const NTV2DoubleArray &inRedLUT, const NTV2DoubleArray &inGreenLUT, const NTV2DoubleArray &inBlueLUT)
Writes the LUT tables.
Definition: ntv2csclut.cpp:998
UWord NTV2DeviceGetNumCSCs(const NTV2DeviceID inDeviceID)
The version number of the LUT(s) on the device.
virtual bool Load1DLUTTable(const NTV2Channel inChannel)
virtual bool SetColorSpaceCustomCoefficients(const NTV2CSCCustomCoeffs &inCustomCoefficients, const NTV2Channel inChannel=NTV2_CHANNEL1)
virtual bool SetColorSpaceMakeAlphaFromKey(const bool inMakeAlphaFromKey, const NTV2Channel inChannel=NTV2_CHANNEL1)
Specifies whether or not the given CSC will produce alpha channel data from its key input...
virtual bool Has12BitLUTSupport(const NTV2Channel inChannel=NTV2_CHANNEL1)
Definition: ntv2csclut.cpp:466
Definition: json.hpp:5362
NTV2LutType
This specifies what function(s) are currently loaded into the LUTs.
Definition: ntv2enums.h:3564
virtual bool GetColorCorrectionHostAccessBank(NTV2ColorCorrectionHostAccessBank &outValue, const NTV2Channel inChannel=NTV2_CHANNEL1)
Definition: ntv2csclut.cpp:339
virtual bool Read12BitLUTTables(UWordSequence &outRedLUT, UWordSequence &outGreenLUT, UWordSequence &outBlueLUT)
uint32_t ULWord
Definition: ajatypes.h:223
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They&#39;re also commonly use...
Definition: ntv2enums.h:1357
static const size_t kLUTArraySize((512) *2)
virtual bool Load3DLUTTable(void)
static const ULWord gChannelDmaLoad[]
Definition: ntv2csclut.cpp:75
static const ULWord gChannelHostLoad[]
Definition: ntv2csclut.cpp:86
virtual bool SetLUTEnable(const bool inEnable, const NTV2Channel inLUT)
Enables or disables the given LUT.
virtual bool GetColorSpaceMakeAlphaFromKey(ULWord &outMakeAlphaFromKey, const NTV2Channel inChannel=NTV2_CHANNEL1)
Answers whether or not the given CSC is set to produce alpha channel data from its key input...
#define true
virtual bool Set1DLUTTableLocation(const NTV2Channel inChannel, const ULWord inFrameNumber, ULWord inLUTIndex=0)
virtual bool SetLUTV3HostAccessBank(const NTV2ColorCorrectionHostAccessBank inValue)
Definition: ntv2csclut.cpp:295
static ULWord intClamp(const int inMin, const int inValue, const int inMax)
Definition: ntv2csclut.cpp:845
NTV2ColorSpaceMethod
Definition: ntv2enums.h:3447
virtual bool ReadRegister(const ULWord inRegNum, ULWord &outValue, const ULWord inMask=0xFFFFFFFF, const ULWord inShift=0)
Reads all or part of the 32-bit contents of a specific register (real or virtual) on the AJA device...
#define NTV2_12BIT_COLORCORRECTOR_WORDSPERTABLE
virtual bool GetColorCorrectionMode(const NTV2Channel inChannel, NTV2ColorCorrectionMode &outMode)
Definition: ntv2csclut.cpp:109
ULWord NTV2FramesizeToByteCount(const NTV2Framesize inFrameSize)
Converts the given NTV2Framesize value into an exact byte count.
Definition: ntv2utils.cpp:5287
NTV2ColorCorrectionMode
Definition: ntv2enums.h:2079
virtual bool LoadLUTTable(const double *pInTable)
virtual bool SetLUTControlSelect(const NTV2LUTControlSelect inLUTSelect)
Definition: ntv2csclut.cpp:456
virtual bool GetColorSpaceCustomCoefficients(NTV2CSCCustomCoeffs &outCustomCoefficients, const NTV2Channel inChannel=NTV2_CHANNEL1)
virtual bool GetColorSpaceUseCustomCoefficient(ULWord &outUseCustomCoefficient, const NTV2Channel inChannel=NTV2_CHANNEL1)
virtual bool GetColorCorrectionOutputBank(const NTV2Channel inLUTWidget, ULWord &outBank)
Answers with the current LUT bank in use for the given LUT.
Definition: ntv2csclut.cpp:170
std::vector< uint16_t > UWordSequence
An ordered sequence of UWord (uint16_t) values.
virtual bool GetColorSpaceMethod(NTV2ColorSpaceMethod &outMethod, const NTV2Channel inChannel=NTV2_CHANNEL1)
Answers with the current operating mode of the given color space converter.
Definition: ntv2csclut.cpp:599
Specifies channel or FrameStore 8 (or the 8th item).
Definition: ntv2enums.h:1366
Specifies channel or FrameStore 2 (or the 2nd item).
Definition: ntv2enums.h:1360
virtual bool SetLUTV2HostAccessBank(const NTV2ColorCorrectionHostAccessBank inValue)
Definition: ntv2csclut.cpp:263
#define kColorCorrectionLUTOffset_Red
NTV2LUTPlaneSelect
Definition: ntv2enums.h:3883
virtual bool GetLUTV2OutputBank(const NTV2Channel inLUTWidget, ULWord &outBank)
Definition: ntv2csclut.cpp:190
static const size_t k12BitLUTArraySize((2048) *2)
virtual bool GetLUTControlSelect(NTV2LUTControlSelect &outLUTSelect)
Definition: ntv2csclut.cpp:461
virtual bool Get12BitLUTTables(NTV2DoubleArray &outRedLUT, NTV2DoubleArray &outGreenLUT, NTV2DoubleArray &outBlueLUT)
virtual bool GetLUTV2HostAccessBank(NTV2ColorCorrectionHostAccessBank &outValue, const NTV2Channel inChannel)
Definition: ntv2csclut.cpp:372
virtual bool GetColorCorrectionSaturation(const NTV2Channel inChannel, ULWord &outValue)
Definition: ntv2csclut.cpp:447
NTV2Framesize
Kona2/Xena2 specific enums.
Definition: ntv2enums.h:2116
virtual bool Load12BitLUTTables(const NTV2DoubleArray &inRedLUT, const NTV2DoubleArray &inGreenLUT, const NTV2DoubleArray &inBlueLUT)
virtual bool DownloadLUTToHW(const NTV2DoubleArray &inRedLUT, const NTV2DoubleArray &inGreenLUT, const NTV2DoubleArray &inBlueLUT, const NTV2Channel inLUT, const int inBank)
Sends the given color lookup tables (LUTs) to the given LUT and bank.
Definition: ntv2csclut.cpp:884
const ULWord LUTTablePartitionSize
virtual bool WriteLUTTables(const UWordSequence &inRedLUT, const UWordSequence &inGreenLUT, const UWordSequence &inBlueLUT)
Writes the LUT tables.
static const ULWord gChannelToCSCoeff34RegNum[]
Definition: ntv2csclut.cpp:49
#define DEC(__x__)
NTV2_CSC_RGB_Range
Definition: ntv2enums.h:3759
UWord NTV2DeviceGetNumLUTs(const NTV2DeviceID inDeviceID)
Declares numerous NTV2 utility functions.
virtual bool SetColorCorrectionHostAccessBank(const NTV2ColorCorrectionHostAccessBank inValue)
Definition: ntv2csclut.cpp:221
#define NTV2_COLORCORRECTOR_WORDSPERTABLE
virtual bool ReadLUTTables(UWordSequence &outRedLUT, UWordSequence &outGreenLUT, UWordSequence &outBlueLUT)
Reads the LUT tables (as raw, unsigned 10-bit integers).
virtual bool SetLUTV2OutputBank(const NTV2Channel inLUTWidget, const ULWord inBank)
Definition: ntv2csclut.cpp:137
uint16_t UWord
Definition: ajatypes.h:221
#define kColorCorrection12BitLUTOffset_Base
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1359
#define kRegColorCorrection12BitLUTOddShift
#define xHEX0N(__x__, __n__)
NTV2ColorSpaceMatrixType
Definition: ntv2enums.h:3458
See Io 4K (UFC Mode).
Definition: ntv2enums.h:38
virtual bool GetLUTTables(NTV2DoubleArray &outRedLUT, NTV2DoubleArray &outGreenLUT, NTV2DoubleArray &outBlueLUT)
Reads the LUT tables (as double-precision floating point values).
Declares the CNTV2Card class.
Specifies channel or FrameStore 4 (or the 4th item).
Definition: ntv2enums.h:1362
static bool GenerateGammaTable(const NTV2LutType inLUTType, const int inBank, NTV2DoubleArray &outTable, const NTV2LutBitDepth inBitDepth=NTV2_LUT10Bit)
Definition: ntv2csclut.cpp:658
Specifies channel or FrameStore 5 (or the 5th item).
Definition: ntv2enums.h:1363
Types and defines shared between NTV2 user application interface and Linux device driver...
The number of LUT widgets on the device.
static const ULWord gChannelToEnhancedCSCRegNum[]
Definition: ntv2csclut.cpp:43
#define kLUTBank_FULL2SMPTE
Definition: ntv2enums.h:3558
NTV2LUTControlSelect
Definition: ntv2enums.h:3876
#define kColorCorrectionLUTV3WidgetOffset
Specifies channel or FrameStore 6 (or the 6th item).
Definition: ntv2enums.h:1364
virtual bool SetColorSpaceRGBBlackRange(const NTV2_CSC_RGB_Range inRange, const NTV2Channel inChannel=NTV2_CHANNEL1)
Sets the RGB range for the given CSC.
#define kColorCorrectionLUTV3WidgetSize
Specifies channel or FrameStore 7 (or the 7th item).
Definition: ntv2enums.h:1365
virtual bool Write12BitLUTTables(const UWordSequence &inRedLUT, const UWordSequence &inGreenLUT, const UWordSequence &inBlueLUT)
virtual bool SetColorSpaceUseCustomCoefficient(const ULWord inUseCustomCoefficient, const NTV2Channel inChannel=NTV2_CHANNEL1)
static const ULWord gChannelTo1DLutControlRegNum[]
Definition: ntv2csclut.cpp:61
virtual bool SetColorSpaceMatrixSelect(const NTV2ColorSpaceMatrixType inType, const NTV2Channel inChannel=NTV2_CHANNEL1)
Sets the matrix type to be used for the given CSC, typically NTV2_Rec601Matrix or NTV2_Rec709Matrix...
Definition: ntv2csclut.cpp:641
virtual bool SetLUTV3OutputBank(const NTV2Channel inLUTWidget, const ULWord inBank)
Definition: ntv2csclut.cpp:155
Declares device capability functions.
#define LUTWARN(__x__)
Definition: ntv2csclut.cpp:31
virtual bool GetLUTV3HostAccessBank(NTV2ColorCorrectionHostAccessBank &outValue, const NTV2Channel inChannel)
Definition: ntv2csclut.cpp:425
Specifies channel or FrameStore 3 (or the 3rd item).
Definition: ntv2enums.h:1361
#define kRegColorCorrection10To12BitLUTEvenShift
virtual bool SetColorCorrectionOutputBank(const NTV2Channel inLUTWidget, const ULWord inBank)
Sets the LUT bank to be used for the given LUT.
Definition: ntv2csclut.cpp:117
Declares the CNTV2RegisterExpert class.
static const ULWord gChannelCapabilities[]
Definition: ntv2csclut.cpp:64
NTV2ColorCorrectionHostAccessBank
Definition: ntv2enums.h:2058