AJA NTV2 SDK  18.1.0.2439
NTV2 SDK 18.1.0.2439
ntv2outputtestpattern.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
9 // Includes
10 #include "ntv2outputtestpattern.h"
11 #include "ntv2devicescanner.h"
12 #include "ntv2testpatterngen.h"
13 #include "ajabase/system/process.h"
14 
15 #define AsULWordPtr(_p_) reinterpret_cast<const ULWord*> (_p_)
16 
17 
18 using namespace std;
19 
20 
21 const uint32_t kAppSignature (NTV2_FOURCC('T','e','s','t'));
22 
23 
24 AJALabelValuePairs TestPatConfig::Get (const bool inCompact) const
25 {
26  AJALabelValuePairs result (PlayerConfig::Get (inCompact));
27  AJASystemInfo::append(result, "Background Pattern", fTestPatternName);
28  return result;
29 }
30 
31 std::ostream & operator << (std::ostream & ioStrm, const TestPatConfig & inObj)
32 {
33  return ioStrm << AJASystemInfo::ToString(inObj.Get());
34 }
35 
36 
38  : mConfig (inConfig),
39  mSavedTaskMode (NTV2_TASK_MODE_INVALID)
40 {
41 } // constructor
42 
43 
45 {
46  if (!mDevice.IsOpen())
47  return;
48  if (!mConfig.fDoMultiFormat)
49  mDevice.ApplySignalRoute(mSavedConnections, /*replace?*/true); // Restore prior widget routing
50 
51  // Restore the prior service level, and release the device...
52  mDevice.SetTaskMode(mSavedTaskMode);
53  if (!mConfig.fDoMultiFormat)
55 
56 } // destructor
57 
58 
60 {
61  // Open the device...
63  { if (aja::lower(mConfig.fDeviceSpec) != "list" && mConfig.fDeviceSpec != "?")
64  cerr << "## ERROR: Device '" << mConfig.fDeviceSpec << "' not found" << endl;
65  return AJA_STATUS_OPEN;
66  }
67  if (!mDevice.IsDeviceReady(false))
68  {cerr << "## ERROR: Device '" << mDevice.GetDisplayName() << "' not ready" << endl; return AJA_STATUS_INITIALIZE;}
69  if (!mDevice.features().CanDoPlayback())
70  {cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' is capture-only" << endl; return AJA_STATUS_FEATURE;}
71 
72  const UWord maxNumChannels (mDevice.features().GetNumFrameStores());
73 
74  if ((mConfig.fOutputChannel == NTV2_CHANNEL1) && (!mDevice.features().CanDoFrameStore1Display()))
75  { // Some older devices (e.g. Corvid1) can only output from FrameStore 2...
76  mConfig.fOutputChannel = NTV2_CHANNEL2;
77  cerr << "## WARNING: '" << mDevice.GetDisplayName() << "' switched to Ch2 (Ch1 is input-only)" << endl;
78  }
79  if (UWord(mConfig.fOutputChannel) >= maxNumChannels)
80  {
81  cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' can't use Ch" << DEC(mConfig.fOutputChannel+1)
82  << " -- only supports Ch1" << (maxNumChannels > 1 ? string("-Ch") + string(1, char(maxNumChannels+'0')) : "") << endl;
84  }
85 
86  mDevice.GetTaskMode(mSavedTaskMode); // Save current task mode
87  if (!mConfig.fDoMultiFormat)
88  {
89  mDevice.GetConnections(mSavedConnections); // Save current routing, so it can be restored later
91  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' can't be acquired -- busy" << endl;
92  return AJA_STATUS_BUSY; // Device is in use by another app -- fail
93  }
94  }
95  mDevice.SetTaskMode(NTV2_OEM_TASKS); // Set OEM service level
96 
97  if (mDevice.features().CanDoMultiFormat())
98  mDevice.SetMultiFormatMode(mConfig.fDoMultiFormat);
99  else
100  mConfig.fDoMultiFormat = false;
101 
102  // Set up the desired video configuration...
103  AJAStatus status (SetUpVideo());
104  if (AJA_FAILURE(status))
105  return status;
106 
107  #if defined(_DEBUG)
108  AJALabelValuePairs info(mConfig.Get());
109  if (!mDevice.GetDescription().empty())
110  for (AJALabelValuePairsConstIter it(info.begin()); it != info.end(); ++it)
111  if (it->first.find("Device Specifier") == 0)
112  {info.insert(++it, AJALabelValuePair("Device Description", mDevice.GetDescription())); break;}
113  cerr << AJASystemInfo::ToString(info);
114  #endif // defined(_DEBUG)
115  return AJA_STATUS_SUCCESS;
116 
117 } // Init
118 
119 
121 {
122  if (mConfig.fVideoFormat == NTV2_FORMAT_UNKNOWN)
123  {
124  // User didn't specify a video format.
125  // Get the device's current video format and use it to create the test pattern...
126  bool enabled(false);
127  mDevice.IsChannelEnabled(mConfig.fOutputChannel, enabled);
128  if (!enabled)
129  if (!mDevice.GetVideoFormat (mConfig.fVideoFormat, mConfig.fOutputChannel))
130  return AJA_STATUS_FAIL;
131 
132  // Read the current VANC mode, as this can affect the NTV2FormatDescriptor and host frame buffer size...
133  if (!mDevice.GetVANCMode (mConfig.fVancMode, mConfig.fOutputChannel))
134  return AJA_STATUS_FAIL;
135  }
136 
137  if (mConfig.fVideoFormat != NTV2_FORMAT_UNKNOWN)
138  {
139  // User specified a video format -- is it legal for this device?
140  if (!mDevice.features().CanDoVideoFormat(mConfig.fVideoFormat))
141  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' cannot do " << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << endl;
142  return AJA_STATUS_UNSUPPORTED;
143  }
144 
145  // Set the video format -- is it legal for this device?
146  if (!mDevice.SetVideoFormat (mConfig.fVideoFormat, /*retail?*/false, /*keepVANC*/false, mConfig.fOutputChannel))
147  { cerr << "## ERROR: SetVideoFormat '" << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << "' failed" << endl;
148  return AJA_STATUS_FAIL;
149  }
150 
151  // Set the VANC mode
153  { cerr << "## ERROR: SetEnableVANCData '" << ::NTV2VANCModeToString(mConfig.fVancMode,true) << "' failed" << endl;
154  return AJA_STATUS_FAIL;
155  }
156  }
157 
158  // 4K/UHD is allowed, but only for devices that can do 12G routing...
159  if (NTV2_IS_4K_VIDEO_FORMAT(mConfig.fVideoFormat) && !mDevice.features().CanDo12gRouting())
160  { cerr << "## ERROR: '" << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << "' requires 12G routing, but '" << mDevice.GetDisplayName() << "' doesn't support it" << endl;
161  return AJA_STATUS_UNSUPPORTED;
162  }
163  // This demo won't do 8K/UHD2
165  { cerr << "## ERROR: This demo only supports SD/HD/2K1080, not '" << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << "'" << endl;
166  return AJA_STATUS_UNSUPPORTED;
167  }
168 
169  // This is a "playback" application, so set the board reference to free run...
170  if (!mDevice.SetReference(NTV2_REFERENCE_FREERUN))
171  return AJA_STATUS_FAIL;
172 
173  // Set the FrameStore's pixel format...
174  if (!mDevice.SetFrameBufferFormat (mConfig.fOutputChannel, mConfig.fPixelFormat))
175  return AJA_STATUS_FAIL;
176 
177  // Enable the FrameStore (if currently disabled)...
178  mDevice.EnableChannel(mConfig.fOutputChannel);
179  if (!mConfig.fDoMultiFormat)
180  { // Disable all other FrameStores...
182  frmStores.erase(frmStores.find(mConfig.fOutputChannel));
183  mDevice.DisableChannels(frmStores);
184  }
185 
186  // Set the FrameStore mode to "playout" (not capture)...
187  if (!mDevice.SetMode (mConfig.fOutputChannel, NTV2_MODE_DISPLAY))
188  return AJA_STATUS_FAIL;
189 
190  // Enable SDI output from the channel being used, but only if the device supports bi-directional SDI...
191  if (mDevice.features().HasBiDirectionalSDI())
192  mDevice.SetSDITransmitEnable (mConfig.fOutputChannel, true);
193 
194  return AJA_STATUS_SUCCESS;
195 
196 } // SetUpVideo
197 
198 
200 {
202  const bool isRGBPixFormat (::IsRGBFormat(mConfig.fPixelFormat));
203 
204  // Build a set of crosspoint connections (input-to-output)
205  // between the relevant signal processing widgets on the device.
206  // By default, the main output crosspoint that feeds the output widget(s) is the FrameStore's video output:
207  NTV2OutputXptID sourceXpt (::GetFrameStoreOutputXptFromChannel(mConfig.fOutputChannel, isRGBPixFormat));
208  if (isRGBPixFormat)
209  { // This code block allows this demo to work with RGB frame buffers, which
210  // necessitate inserting a CSC between the FrameStore and the video output(s)...
211  NTV2Connection csc_framestore (::GetCSCInputXptFromChannel(mConfig.fOutputChannel), sourceXpt);
212  connections.insert(csc_framestore); // CSC video input to FrameStore output
213  sourceXpt = ::GetCSCOutputXptFromChannel(mConfig.fOutputChannel); // CSC output will feed all output widget(s)
214  }
215 
216  // Route sourceXpt to SDI output(s)...
217  const NTV2ChannelSet sdiOutputs (mConfig.fDoMultiFormat ? ::NTV2MakeChannelSet (mConfig.fOutputChannel, 1)
219  mDevice.features().GetNumVideoOutputs()));
220  const NTV2Standard videoStd (::GetNTV2StandardFromVideoFormat(mConfig.fVideoFormat));
221  const NTV2ChannelList sdiOuts (::NTV2MakeChannelList(sdiOutputs));
222 
223  // For every SDI output, set video standard, and disable level A/B conversion...
224  mDevice.SetSDIOutputStandard (sdiOutputs, videoStd);
225  mDevice.SetSDIOutLevelAtoLevelBConversion (sdiOutputs, false);
226  mDevice.SetSDIOutRGBLevelAConversion (sdiOutputs, false);
227 
228  // Connect each SDI output to the main output crosspoint...
229  bool canCheck(mDevice.features().HasCrosspointConnectROM());
230  for (size_t ndx(0); ndx < sdiOutputs.size(); ndx++)
231  {
232  const NTV2Connection sdiConnection(::GetSDIOutputInputXpt(sdiOuts.at(ndx)), sourceXpt);
233  bool canConnect(true);
234  if (!canCheck || (canCheck && mDevice.CanConnect(sdiConnection, canConnect) && canConnect))
235  connections.insert(sdiConnection);
236  if (mDevice.features().HasBiDirectionalSDI()) // If device has bi-directional SDIs...
237  mDevice.SetSDITransmitEnable (sdiOutputs, true); // ... be sure it's set to "transmit"
238  }
239 
240  // Add analog video output, if the device has one...
241  if (!mConfig.fDoMultiFormat && mDevice.features().GetNumAnalogVideoOutputs())
243 
244  // Add HDMI video output, if the device has one...
245  if (!mConfig.fDoMultiFormat && mDevice.features().GetNumHDMIVideoOutputs())
247 
248  // Apply all the accumulated connections...
249  mDevice.ApplySignalRoute(connections, /*replaceExistingRoutes*/true);
250 
251 } // RouteOutputSignal
252 
253 
255 {
256  // Connect the FrameStore to the video output...
258 
259  // Allocate a host video buffer that will hold our test pattern raster...
260  NTV2FormatDescriptor fd (mConfig.fVideoFormat, mConfig.fPixelFormat, mConfig.fVancMode);
261  NTV2Buffer hostBuffer (fd.GetTotalBytes());
262  if (hostBuffer.IsNULL())
263  return false;
264 
265  // Write the requested test pattern into host buffer...
266  NTV2TestPatternGen testPatternGen;
267  testPatternGen.setVANCToLegalBlack(fd.IsVANC());
268  if (!testPatternGen.DrawTestPattern (mConfig.fTestPatternName, fd, hostBuffer))
269  return false;
270 
271  // Find out which frame is currently being output from the frame store...
272  uint32_t currentOutputFrame(0);
273  if (!mDevice.GetOutputFrame (mConfig.fOutputChannel, currentOutputFrame))
274  return false; // ReadRegister failure?
275 
276  // Now simply transfer the contents of the host buffer to the device's current output frame...
277  return mDevice.DMAWriteFrame (currentOutputFrame, // Device frame number
278  AsULWordPtr(fd.GetRowAddress(hostBuffer.GetHostPointer(), 0)), // Host buffer address
279  ULWord(hostBuffer.GetByteCount())); // # bytes to xfer
280 } // EmitPattern
AJALabelValuePairs Get(const bool inCompact=(0)) const
Renders a human-readable representation of me.
#define NTV2_IS_VANCMODE_TALLER(__v__)
Definition: ntv2enums.h:3813
virtual bool SetTaskMode(const NTV2TaskMode inMode)
Sets the device&#39;s task mode.
bool setVANCToLegalBlack(void) const
AJAStatus Init(void)
Initializes me and prepares me to Run.
virtual bool GetVideoFormat(NTV2VideoFormat &outValue, NTV2Channel inChannel=NTV2_CHANNEL1)
Specifies the device&#39;s internal clock.
Definition: ntv2enums.h:1464
AJALabelValuePairs Get(const bool inCompact=(0)) const
virtual bool SetReference(const NTV2ReferenceSource inRefSource, const bool inKeepFramePulseSelect=(0))
Sets the device&#39;s clock reference source. See Video Output Clocking & Synchronization for more inform...
virtual bool ReleaseStreamForApplication(ULWord inApplicationType, int32_t inProcessID)
Releases exclusive use of the AJA device for the given process, permitting other processes to acquire...
The NTV2 test pattern generator.
virtual bool SetVideoFormat(const NTV2VideoFormat inVideoFormat, const bool inIsAJARetail=(!(0)), const bool inKeepVancSettings=(0), const NTV2Channel inChannel=NTV2_CHANNEL1)
Configures the AJA device to handle a specific video format.
AJAStatus
Definition: types.h:380
NTV2VANCMode fVancMode
VANC mode to use.
virtual bool IsDeviceReady(const bool inCheckValid=(0))
Configures an NTV2OutputTestPattern instance.
static uint64_t GetPid()
Definition: process.cpp:35
std::string fTestPatternName
Name of the test pattern to use.
#define AJA_FAILURE(_status_)
Definition: types.h:373
Declares the NTV2TestPatternGen class.
virtual bool DMAWriteFrame(const ULWord inFrameNumber, const ULWord *pInFrameBuffer, const ULWord inByteCount)
Transfers a single frame from the host to the AJA device.
Definition: ntv2dma.cpp:65
virtual bool GetOutputFrame(const NTV2Channel inChannel, ULWord &outValue)
Answers with the current output frame number for the given FrameStore (expressed as an NTV2Channel)...
std::vector< AJALabelValuePair > AJALabelValuePairs
An ordered sequence of label/value pairs.
Definition: info.h:71
#define NTV2_IS_4K_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:787
#define NTV2_FOURCC(_a_, _b_, _c_, _d_)
ULWord GetTotalBytes(void) const
#define NTV2_IS_8K_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:897
Definition: json.hpp:5362
AJALabelValuePairs::const_iterator AJALabelValuePairsConstIter
Definition: info.h:72
std::string fDeviceSpec
The AJA device to use.
std::pair< NTV2InputXptID, NTV2OutputXptID > NTV2Connection
This links an NTV2InputXptID and an NTV2OutputXptID.
uint32_t ULWord
Definition: ajatypes.h:236
virtual bool SetFrameBufferFormat(NTV2Channel inChannel, NTV2FrameBufferFormat inNewFormat, bool inIsAJARetail=(!(0)), NTV2HDRXferChars inXferChars=NTV2_VPID_TC_SDR_TV, NTV2HDRColorimetry inColorimetry=NTV2_VPID_Color_Rec709, NTV2HDRLuminance inLuminance=NTV2_VPID_Luminance_YCbCr)
Sets the frame buffer format for the given FrameStore on the AJA device.
const void * GetRowAddress(const void *pInStartAddress, const ULWord inRowIndex0, const UWord inPlaneIndex0=0) const
virtual class DeviceCapabilities & features(void)
Definition: ntv2card.h:148
virtual bool SetMultiFormatMode(const bool inEnable)
Enables or disables multi-format (per channel) device operation. If enabled, each device channel can ...
NTV2ChannelList NTV2MakeChannelList(const NTV2Channel inFirstChannel, const UWord inNumChannels=1)
virtual bool GetTaskMode(NTV2TaskMode &outMode)
Retrieves the device&#39;s current task mode.
virtual bool DrawTestPattern(const std::string &inTPName, const NTV2FormatDescriptor &inFormatDesc, NTV2Buffer &inBuffer)
Renders the given test pattern or color into a host raster buffer.
NTV2Standard
Identifies a particular video standard.
Definition: ntv2enums.h:169
virtual bool CanConnect(const NTV2InputCrosspointID inInputXpt, const NTV2OutputCrosspointID inOutputXpt, bool &outCanConnect)
Answers whether or not the given widget signal input (sink) can legally be connected to the given sig...
Playout (output) mode, which reads from device SDRAM.
Definition: ntv2enums.h:1245
virtual std::string GetDescription(void) const
Definition: ntv2card.cpp:139
virtual bool SetMode(const NTV2Channel inChannel, const NTV2Mode inNewValue, const bool inIsRetail=(!(0)))
Determines if a given FrameStore on the AJA device will be used to capture or playout video...
NTV2InputXptID GetOutputDestInputXpt(const NTV2OutputDestination inOutputDest, const bool inIsSDI_DS2=false, const UWord inHDMI_Quadrant=99)
virtual bool IsOpen(void) const
NTV2OutputTestPattern(const TestPatConfig &inConfig)
Constructs me using the given configuration settings.
static bool GetFirstDeviceFromArgument(const std::string &inArgument, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the AJA device that matches a command li...
virtual bool SetSDITransmitEnable(const NTV2Channel inChannel, const bool inEnable)
Sets the specified bidirectional SDI connector to act as an input or an output.
virtual bool AcquireStreamForApplication(ULWord inApplicationType, int32_t inProcessID)
Reserves exclusive use of the AJA device for a given process, preventing other processes on the host ...
virtual bool GetVANCMode(NTV2VANCMode &outVancMode, const NTV2Channel inChannel=NTV2_CHANNEL1)
Retrieves the current VANC mode for the given FrameStore.
virtual std::string GetDisplayName(void)
Answers with this device&#39;s display name.
Definition: ntv2card.cpp:88
NTV2InputXptID GetCSCInputXptFromChannel(const NTV2Channel inCSC, const bool inIsKeyInput=false)
Describes a video frame for a given video standard or format and pixel format, including the total nu...
NTV2PixelFormat fPixelFormat
The pixel format to use.
2: OEM (recommended): device configured by client application(s) with some driver involvement...
std::string NTV2VANCModeToString(const NTV2VANCMode inValue, const bool inCompactDisplay=false)
Definition: ntv2utils.cpp:6509
virtual bool ApplySignalRoute(const CNTV2SignalRouter &inRouter, const bool inReplace=(0))
Applies the given routing table to the AJA device.
bool EmitPattern(void)
Generates, transfers and displays the test pattern on the output.
NTV2XptConnections connections
Definition: ntv2vcam.cpp:1011
NTV2VideoFormat fVideoFormat
The video format to use.
std::string NTV2VideoFormatToString(const NTV2VideoFormat inValue, const bool inUseFrameRate=false)
Definition: ntv2utils.cpp:6750
Specifies channel or FrameStore 2 (or the 2nd item).
Definition: ntv2enums.h:1364
const uint32_t kAppSignature(((((uint32_t)( 'T'))<< 24)|(((uint32_t)( 'e'))<< 16)|(((uint32_t)( 's'))<< 8)|(((uint32_t)( 't'))<< 0)))
#define NTV2_IS_VANCMODE_ON(__v__)
Definition: ntv2enums.h:3814
Declares the CNTV2DeviceScanner class.
Declares the AJAProcess class.
Describes a user-space buffer on the host computer. I have an address and a length, plus some optional attributes (allocated by SDK?, page-aligned? etc.).
bool fDoMultiFormat
If true, enable device-sharing; otherwise take exclusive control of device.
bool IsRGBFormat(const NTV2FrameBufferFormat format)
Definition: ntv2utils.cpp:5414
static AJALabelValuePairs & append(AJALabelValuePairs &inOutTable, const std::string &inLabel, const std::string &inValue=std::string())
A convenience function that appends the given label and value strings to the provided AJALabelValuePa...
Definition: info.h:170
#define DEC(__x__)
std::set< NTV2Channel > NTV2ChannelSet
A set of distinct NTV2Channel values.
NTV2Channel fOutputChannel
The device channel to use.
virtual bool DisableChannels(const NTV2ChannelSet &inChannels)
Disables the given FrameStore(s).
virtual bool SetSDIOutRGBLevelAConversion(const UWord inOutputSpigot, const bool inEnable)
Enables or disables an RGB-over-3G-level-A conversion at the SDI output widget (assuming the AJA devi...
AJAStatus SetUpVideo(void)
Sets up my AJA device to play video.
virtual bool SetSDIOutLevelAtoLevelBConversion(const UWord inOutputSpigot, const bool inEnable)
Enables or disables 3G level A to 3G level B conversion at the SDI output widget (assuming the AJA de...
NTV2OutputXptID GetFrameStoreOutputXptFromChannel(const NTV2Channel inFrameStore, const bool inIsRGB=false, const bool inIs425=false)
uint16_t UWord
Definition: ajatypes.h:234
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1363
virtual bool SetEnableVANCData(const bool inVANCenabled, const bool inTallerVANC, const NTV2Standard inStandard, const NTV2FrameGeometry inGeometry, const NTV2Channel inChannel=NTV2_CHANNEL1)
#define AsULWordPtr(_p_)
UWord GetNumAnalogVideoOutputs(void)
virtual bool IsChannelEnabled(const NTV2Channel inChannel, bool &outEnabled)
Answers whether or not the given FrameStore is enabled.
NTV2ChannelSet NTV2MakeChannelSet(const NTV2Channel inFirstChannel, const UWord inNumChannels=1)
NTV2Standard GetNTV2StandardFromVideoFormat(const NTV2VideoFormat inVideoFormat)
Definition: ntv2utils.cpp:2375
std::vector< NTV2Channel > NTV2ChannelList
An ordered sequence of NTV2Channel values.
void RouteOutputSignal(void)
Sets up board routing for playout.
std::map< NTV2InputXptID, NTV2OutputXptID > NTV2XptConnections
std::ostream & operator<<(std::ostream &ioStrm, const TestPatConfig &inObj)
bool CanDoVideoFormat(const NTV2VideoFormat inVF)
std::pair< std::string, std::string > AJALabelValuePair
A pair of strings comprising a label and a value.
Definition: info.h:70
std::string & lower(std::string &str)
Definition: common.cpp:436
virtual bool SetSDIOutputStandard(const UWord inOutputSpigot, const NTV2Standard inValue)
Sets the SDI output spigot&#39;s video standard.
NTV2InputXptID GetSDIOutputInputXpt(const NTV2Channel inSDIOutput, const bool inIsDS2=false)
virtual void ToString(std::string &outAllLabelsAndValues) const
Answers with a multi-line string that contains the complete host system info table.
enum NTV2OutputCrosspointID NTV2OutputXptID
virtual bool GetConnections(NTV2XptConnections &outConnections)
Answers with the device&#39;s current widget routing connections.
NTV2OutputXptID GetCSCOutputXptFromChannel(const NTV2Channel inCSC, const bool inIsKey=false, const bool inIsRGB=false)
virtual bool EnableChannel(const NTV2Channel inChannel)
Enables the given FrameStore.