AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
ntv2autocirculate.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2card.h"
9 #include "ntv2utils.h"
10 #include "ntv2rp188.h"
11 #include "ntv2endian.h"
12 #include "ajabase/system/lock.h"
13 #include "ajabase/system/debug.h"
17 #include "ajabase/common/common.h"
18 #include <iomanip>
19 #include <assert.h>
20 #include <algorithm>
21 
22 
23 using namespace std;
24 
25 #if defined(MSWindows)
26  #undef min
27 #endif
28 
29 #if 0
30  // Debug builds can clear Anc buffers during A/C capture
31  #define AJA_NTV2_CLEAR_DEVICE_ANC_BUFFER_AFTER_CAPTURE_XFER // Requires non-zero kVRegZeroDeviceAncPostCapture
32  #define AJA_NTV2_CLEAR_HOST_ANC_BUFFER_TAIL_AFTER_CAPTURE_XFER // Requires non-zero kVRegZeroHostAncPostCapture
33 #endif // _DEBUG
34 
35 // Logging Macros
36 #define ACINSTP(_p_) " " << HEX0N(uint64_t(_p_),8)
37 #define ACTHIS ACINSTP(this)
38 
39 #define ACFAIL(__x__) AJA_sERROR (AJA_DebugUnit_AutoCirculate, ACTHIS << "::" << AJAFUNC << ": " << __x__)
40 #define ACWARN(__x__) AJA_sWARNING(AJA_DebugUnit_AutoCirculate, ACTHIS << "::" << AJAFUNC << ": " << __x__)
41 #define ACNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_AutoCirculate, ACTHIS << "::" << AJAFUNC << ": " << __x__)
42 #define ACINFO(__x__) AJA_sINFO (AJA_DebugUnit_AutoCirculate, ACTHIS << "::" << AJAFUNC << ": " << __x__)
43 #define ACDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_AutoCirculate, ACTHIS << "::" << AJAFUNC << ": " << __x__)
44 
45 #define RCVFAIL(__x__) AJA_sERROR (AJA_DebugUnit_Anc2110Rcv, ACTHIS << "::" << AJAFUNC << ": " << __x__)
46 #define RCVWARN(__x__) AJA_sWARNING(AJA_DebugUnit_Anc2110Rcv, ACTHIS << "::" << AJAFUNC << ": " << __x__)
47 #define RCVNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_Anc2110Rcv, ACTHIS << "::" << AJAFUNC << ": " << __x__)
48 #define RCVINFO(__x__) AJA_sINFO (AJA_DebugUnit_Anc2110Rcv, ACTHIS << "::" << AJAFUNC << ": " << __x__)
49 #define RCVDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_Anc2110Rcv, ACTHIS << "::" << AJAFUNC << ": " << __x__)
50 
51 #define XMTFAIL(__x__) AJA_sERROR (AJA_DebugUnit_Anc2110Xmit, ACTHIS << "::" << AJAFUNC << ": " << __x__)
52 #define XMTWARN(__x__) AJA_sWARNING(AJA_DebugUnit_Anc2110Xmit, ACTHIS << "::" << AJAFUNC << ": " << __x__)
53 #define XMTNOTE(__x__) AJA_sNOTICE (AJA_DebugUnit_Anc2110Xmit, ACTHIS << "::" << AJAFUNC << ": " << __x__)
54 #define XMTINFO(__x__) AJA_sINFO (AJA_DebugUnit_Anc2110Xmit, ACTHIS << "::" << AJAFUNC << ": " << __x__)
55 #define XMTDBG(__x__) AJA_sDEBUG (AJA_DebugUnit_Anc2110Xmit, ACTHIS << "::" << AJAFUNC << ": " << __x__)
56 
57 
58 static const char gFBAllocLockName[] = "com.aja.ntv2.mutex.FBAlloc";
59 static AJALock gFBAllocLock(gFBAllocLockName); // New in SDK 15: Global mutex to avoid device frame buffer allocation race condition
60 
61 
62 //GetFrameStamp(NTV2Crosspoint channelSpec, ULONG frameNum, FRAME_STAMP_STRUCT* pFrameStamp)
63 //When a channelSpec is autocirculating, the ISR or DPC will continously fill in a
64 // FRAME_STAMP_STRUCT for the frame it is working on.
65 // The framestamp structure is intended to give enough information to determine if frames
66 // have been dropped either on input or output. It also allows for synchronization of
67 // audio and video by stamping the audioinputaddress at the start and end of a video frame.
68 bool CNTV2Card::GetFrameStamp (NTV2Crosspoint channelSpec, ULWord frameNum, FRAME_STAMP_STRUCT* pFrameStamp)
69 {
70  // Insure that the CNTV2Card has been 'open'ed
71  if (! _boardOpened ) return false;
72 
73  // Fill in our OS independent data structure
74  AUTOCIRCULATE_DATA autoCircData (eGetFrameStamp, channelSpec);
75  autoCircData.lVal1 = LWord(frameNum);
76  autoCircData.pvVal1 = PVOID(pFrameStamp);
77 
78  // The following is ignored by Windows; it looks at the
79  // channel spec and frame num in the autoCircData instead.
80  pFrameStamp->channelSpec = channelSpec;
81  pFrameStamp->frame = frameNum;
82 
83  // Call the OS specific method
84  return AutoCirculate (autoCircData);
85 }
86 
87 // GetAutoCirculate(NTV2Crosspoint channelSpec,AUTOCIRCULATE_STATUS_STRUCT* autoCirculateStatus )
88 // Returns true if communication with the driver was successful.
89 // Passes back: whether associated channelSpec is currently autocirculating;
90 // Frame Range (Start and End); and Current Active Frame.
91 //
92 // Note that Current Active Frame is reliable,
93 // whereas reading, for example, the Ch1OutputFrame register is not reliable,
94 // because the latest-written value may or may-not have been clocked-in to the hardware.
95 // Note also that this value is valid only if bIsCirculating is true.
97 {
98  // Insure that the CNTV2Card has been 'open'ed
99  if (!_boardOpened) return false;
100 
101  // The following is ignored by Windows.
102  autoCirculateStatus -> channelSpec = channelSpec;
103 
104  // Fill in our OS independent data structure
105  AUTOCIRCULATE_DATA autoCircData (eGetAutoCirc, channelSpec);
106  autoCircData.pvVal1 = PVOID(autoCirculateStatus);
107 
108  // Call the OS specific method
109  return AutoCirculate (autoCircData);
110 }
111 
112 
113 bool CNTV2Card::FindUnallocatedFrames (const UWord inFrameCount, LWord & outStartFrame, LWord & outEndFrame, const NTV2Channel inFrameStore)
114 {
115  outStartFrame = outEndFrame = -1;
116  if (!IsOpen())
117  {ACFAIL(GetDescription() << ": Not open"); return false;}
118  if (!inFrameCount)
119  {ACFAIL(GetDescription() << ": Must request at least one frame"); return false;}
120 
121  // Before inventorying SDRAM, disable the framestore(s) of interest (if enabled),
122  // to maximize contiguous available free memory (since those frames will be re-utilized anyway)...
124  NTV2ChannelSet enabledFrameStores;
125  bool isQuad(false), isQuadQuad(false), wasEnabled(false);
126  if (inFrameStore != NTV2_CHANNEL_INVALID) // Caller wants to utilize a specific FrameStore?
127  {
128  NTV2Channel ch(inFrameStore);
129  while (IsChannelEnabled(ch, wasEnabled) && wasEnabled) // Is it currently enabled?
130  {
131  enabledFrameStores.insert(ch);
132  if (enabledFrameStores.size() == 1)
133  {
134  GetVideoFormat(vFmt, inFrameStore); // Get its video format
135  isQuad = NTV2_IS_QUAD_FRAME_FORMAT(vFmt); // Is quad format?
136  isQuadQuad = NTV2_IS_QUAD_QUAD_FORMAT(vFmt); // Is quad-quad format?
137  if (!isQuad && !isQuadQuad)
138  break;
139  }
140  ch = NTV2Channel(ch+1);
141  if (UWord(ch) > (UWord(inFrameStore)+1))
142  break;
143  }
144  DisableChannels(enabledFrameStores); // Temporarily disable it/them, to preclude it/them from fragmenting free memory
145  }
146 
147  // Inventory device SDRAM utilization...
148  SDRAMAuditor auditor(*this); // Using this constructor automatically excludes audio buffers from consideration, by default
149  ULWordSequence freeRgns8MB, freeRgns;
150  auditor.GetFreeRegions (freeRgns8MB);
151  if (!enabledFrameStores.empty())
152  EnableChannels(enabledFrameStores); // Restore FrameStore enabled state
153 
154  if (freeRgns8MB.empty())
155  {ACFAIL(GetDescription() << ": No free regions"); return false;}
156  if (!auditor.TranslateRegions (freeRgns, freeRgns8MB, isQuad, isQuadQuad))
157  {ACFAIL(GetDescription() << ": TranslateRegions failed"); return false;}
158  if (freeRgns.empty())
159  {ACFAIL(GetDescription() << ": No free regions after translation"); return false;}
160 
161  // Look for first free region whose length >= inFrameCount...
162  for (size_t ndx(0); ndx < freeRgns.size(); ndx++)
163  { const ULWord val(freeRgns.at(ndx));
164  UWord startFrame(val >> 16), lengthFrames(UWord(val & 0x0000FFFF));
165  if (inFrameCount > lengthFrames) // Will it fit?
166  continue; // No, skip it
167  // Yes -- use it
168  outStartFrame = LWord(startFrame);
169  outEndFrame = LWord(startFrame + inFrameCount - 1);
170  break; // Done, found!
171  }
172  const string qstr (isQuad ? " quad" : (isQuadQuad ? " quad-quad" : ""));
173  if (outStartFrame < 0 || outEndFrame < 0)
174  {
175  #if defined(_DEBUG)
176  auditor.DumpBlocks(cerr);
177  #endif // _DEBUG
178  ostringstream dump; dump << DEC(freeRgns.size()) << " free region(s):" << endl;
179  if (!freeRgns.empty())
180  dump << " Tgt Frms 8MB Frms" << endl;
181  for (size_t ndx(0); ndx < freeRgns.size(); ndx++)
182  { ULWord rgn(freeRgns.at(ndx)), rgn8(freeRgns8MB.at(ndx));
183  UWord startBlk(rgn >> 16), numBlks(UWord(rgn & 0x0000FFFF));
184  UWord startBlk8(rgn8 >> 16), numBlks8(UWord(rgn8 & 0x0000FFFF));
185  if (numBlks > 1)
186  dump << "Frms " << DEC0N(startBlk,3) << "-" << DEC0N(startBlk+numBlks-1,3) << " ";
187  else
188  dump << "Frm " << DEC0N(startBlk,3) << " ";
189  if (numBlks8 > 1)
190  dump << DEC0N(startBlk8,3) << "-" << DEC0N(startBlk8+numBlks8-1,3) << endl;
191  else
192  dump << DEC0N(startBlk8,3) << endl;
193  }
194  ACFAIL(GetDescription() << ": Cannot find " << DEC(inFrameCount) << " contiguous" << qstr << " frames in these " << dump.str());
195  return false;
196  }
197  ACINFO(GetDescription() << ": Found requested " << DEC(inFrameCount) << " contiguous" << qstr << " frames (" << DEC(outStartFrame) << "-" << DEC(outEndFrame) << ")");
198  return true;
199 
200 } // FindUnallocatedFrames
201 
202 
203 // Handy function to fetch the NTV2Crosspoint for a given NTV2Channel that works with both pre & post 12.3 drivers.
204 // NOTE: This relies on the channel's NTV2Mode being correct and aligned with the driver's NTV2Crosspoint!
205 static bool GetCurrentACChannelCrosspoint (CNTV2Card & inDevice, const NTV2Channel inChannel, NTV2Crosspoint & outCrosspoint)
206 {
208  outCrosspoint = NTV2CROSSPOINT_INVALID;
209  if (!inDevice.IsOpen ())
210  return false;
211  if (!NTV2_IS_VALID_CHANNEL (inChannel))
212  return false;
213 
214  if (!inDevice.GetMode (inChannel, mode))
215  return false;
216  outCrosspoint = (mode == NTV2_MODE_DISPLAY) ? ::NTV2ChannelToOutputCrosspoint (inChannel) : ::NTV2ChannelToInputCrosspoint (inChannel);
217  return true;
218 }
219 
220 
222  const UWord inFrameCount,
223  const NTV2AudioSystem inAudioSystem,
224  const ULWord inOptionFlags,
225  const UByte inNumChannels,
226  const UWord inStartFrameNumber,
227  const UWord inEndFrameNumber)
228 {
229  if (!NTV2_IS_VALID_CHANNEL(inChannel))
230  {ACFAIL(GetDescription() << ": Ch" << DEC(inChannel+1) << " is illegal channel value"); return false;} // Must be valid channel
231  if (!inNumChannels || inNumChannels > 8)
232  {ACFAIL(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": illegal 'inNumChannels' value '" << DEC(inNumChannels) << "' -- must be 1-8"); return false;} // At least one channel
233  if (!gFBAllocLock.IsValid())
234  {ACFAIL(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": FBAllocLock mutex not ready"); return false;} // Mutex not ready
235 
236  AJAAutoLock autoLock (&gFBAllocLock); // Avoid AutoCirculate buffer collisions
237  LWord startFrameNumber(LWord(inStartFrameNumber+0));
238  LWord endFrameNumber (LWord(inEndFrameNumber+0));
239  if (!endFrameNumber && !startFrameNumber)
240  {
241  if (!inFrameCount)
242  {ACFAIL(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": Zero frames requested"); return false;}
243  if (!FindUnallocatedFrames (inFrameCount, startFrameNumber, endFrameNumber, inChannel))
244  return false;
245  }
246  else if (inFrameCount)
247  ACWARN (GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": FrameCount " << DEC(inFrameCount) << " ignored -- using start/end " << DEC(inStartFrameNumber)
248  << "/" << DEC(inEndFrameNumber) << " frame numbers");
249  if (endFrameNumber < startFrameNumber) // endFrame must be > startFrame
250  {ACFAIL(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": EndFrame(" << DEC(endFrameNumber) << ") precedes StartFrame(" << DEC(startFrameNumber) << ")"); return false;}
251  if ((endFrameNumber - startFrameNumber + 1) < 2) // must be at least 2 frames
252  {ACFAIL(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": Frames " << DEC(startFrameNumber) << "-" << DEC(endFrameNumber) << " < 2 frames"); return false;}
253  if (startFrameNumber >= MAX_FRAMEBUFFERS)
254  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": Start frame " << DEC(startFrameNumber) << " exceeds max " << DEC(MAX_FRAMEBUFFERS-1)); return false;}
255  if (endFrameNumber >= MAX_FRAMEBUFFERS)
256  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": End frame " << DEC(endFrameNumber) << " exceeds max " << DEC(MAX_FRAMEBUFFERS-1)); return false;}
258  ACWARN(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": MultiLink Audio requested, but device doesn't support it");
259  const UWord numAudSystems(UWord(GetNumSupported(kDeviceGetNumAudioSystems))); // AutoCirc cannot use AudioMixer or HostAudio
260  if (inAudioSystem != NTV2_AUDIOSYSTEM_INVALID)
261  {
262  if (numAudSystems && UWord(inAudioSystem) >= numAudSystems)
263  {ACFAIL(GetDescription() << ": Invalid audio system specified: AudSys" << DEC(inAudioSystem+1) << " -- exceeds max legal AudSys" << DEC(numAudSystems)); return false;}
264  }
265 
266  // Fill in our OS independent data structure...
268  autoCircData.lVal1 = startFrameNumber;
269  autoCircData.lVal2 = endFrameNumber;
270  autoCircData.lVal3 = inAudioSystem;
271  if (inOptionFlags & AUTOCIRCULATE_WITH_MULTILINK_AUDIO1)
272  autoCircData.lVal3 |= NTV2_AUDIOSYSTEM_Plus1;
273  if (inOptionFlags & AUTOCIRCULATE_WITH_MULTILINK_AUDIO2)
274  autoCircData.lVal3 |= NTV2_AUDIOSYSTEM_Plus2;
275  if (inOptionFlags & AUTOCIRCULATE_WITH_MULTILINK_AUDIO3)
276  autoCircData.lVal3 |= NTV2_AUDIOSYSTEM_Plus3;
277  autoCircData.lVal4 = inNumChannels;
278  if (inOptionFlags & AUTOCIRCULATE_WITH_FIELDS)
279  autoCircData.lVal6 |= AUTOCIRCULATE_WITH_FIELDS;
280  if (inOptionFlags & AUTOCIRCULATE_WITH_HDMIAUX)
281  autoCircData.lVal6 |= AUTOCIRCULATE_WITH_HDMIAUX;
282  if (inOptionFlags & AUTOCIRCULATE_WITH_AUDIO_CONTROL)
283  autoCircData.bVal1 = false;
284  else
285  autoCircData.bVal1 = NTV2_IS_VALID_AUDIO_SYSTEM(inAudioSystem) ? true : false;
286  autoCircData.bVal2 = inOptionFlags & AUTOCIRCULATE_WITH_RP188 ? true : false;
287  autoCircData.bVal3 = inOptionFlags & AUTOCIRCULATE_WITH_FBFCHANGE ? true : false;
288  autoCircData.bVal4 = inOptionFlags & AUTOCIRCULATE_WITH_FBOCHANGE ? true : false;
289  autoCircData.bVal5 = inOptionFlags & AUTOCIRCULATE_WITH_COLORCORRECT ? true : false;
290  autoCircData.bVal6 = inOptionFlags & AUTOCIRCULATE_WITH_VIDPROC ? true : false;
291  autoCircData.bVal7 = inOptionFlags & AUTOCIRCULATE_WITH_ANC ? true : false;
292  autoCircData.bVal8 = inOptionFlags & AUTOCIRCULATE_WITH_LTC ? true : false;
293 
294  const bool result (AutoCirculate(autoCircData)); // Call the OS-specific method
295  if (result)
296  { // Success!
297  #if 1
298  // Warn about interference from other channels...
299  ULWordSequence badRgns;
300  SDRAMAuditor auditor(*this);
301  auditor.GetBadRegions(badRgns);
302  for (size_t ndx(0); ndx < badRgns.size(); ndx++)
303  { const ULWord rgnInfo(badRgns.at(ndx));
304  const UWord startBlk(rgnInfo >> 16), numBlks(UWord(rgnInfo & 0x0000FFFF));
305  NTV2StringSet tags;
306  auditor.GetTagsForFrameIndex (startBlk, tags);
307  const string infoStr (aja::join(tags, ", "));
308  ostringstream acLabel; acLabel << "AC" << DEC(inChannel+1); // Search for label e.g. "AC2"
309  if (infoStr.find(acLabel.str()) != string::npos)
310  { ostringstream warning;
311  if (numBlks > 1)
312  warning << "Frms " << DEC0N(startBlk,3) << "-" << DEC0N(startBlk+numBlks-1,3);
313  else
314  warning << "Frm " << DEC0N(startBlk,3);
315  ACWARN(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": memory overlap/interference: " << warning.str() << ": " << infoStr);
316  }
317  } // for each "bad" region
318  #endif
319  #if 1
320  { AUTOCIRCULATE_STATUS stat;
321  if (AutoCirculateGetStatus (inChannel, stat) && !stat.IsStopped() && stat.WithAudio())
322  { // Not stopped and AutoCirculating audio -- check if audio buffer capacity will be exceeded...
323  ULWord audChlsPerSample(0);
326  GetNumberAudioChannels (audChlsPerSample, stat.GetAudioSystem());
327  if (GetFrameRate (fr, inChannel) && NTV2_IS_SUPPORTED_NTV2FrameRate(fr))
328  if (GetAudioRate (ar, stat.GetAudioSystem()) && NTV2_IS_VALID_AUDIO_RATE(ar))
329  {
330  const double framesPerSecond (double(::GetScaleFromFrameRate(fr)) / 100.00);
331  const double samplesPerSecond (double(::GetAudioSamplesPerSecond(ar)));
332  const double bytesPerChannel (4.0);
333  const double channelsPerSample (double(audChlsPerSample+0));
334  const double bytesPerFrame (samplesPerSecond * bytesPerChannel * channelsPerSample / framesPerSecond);
335  const ULWord maxVideoFrames (4UL * 1024UL * 1024UL / ULWord(bytesPerFrame));
336  if (stat.GetFrameCount() > maxVideoFrames)
337  ACWARN(GetDescription() << ": Input Ch" << DEC(inChannel+1) << ": " << DEC(stat.GetFrameCount()) << " frames ("
338  << DEC(stat.GetStartFrame()) << "-" << DEC(stat.GetEndFrame()) << ") exceeds "
339  << DEC(maxVideoFrames) << "-frame max buffer capacity of AudSys" << DEC(stat.GetAudioSystem()+1));
340  }
341  }
342  }
343  #endif
344  ACINFO(GetDescription() << ": Input Ch" << DEC(inChannel+1) << " initialized using frames " << DEC(startFrameNumber) << "-" << DEC(endFrameNumber));
345  }
346  else
347  ACFAIL(GetDescription() << ": Input Ch" << DEC(inChannel+1) << " initialization failed");
348  return result;
349 
350 } // AutoCirculateInitForInput
351 
353  const NTV2ACFrameRange & inFrameRange,
354  const NTV2AudioSystem inAudioSystem,
355  const ULWord inOptionFlags,
356  const UByte inNumChannels)
357 {
358  return inFrameRange ? AutoCirculateInitForInput (inChannel, inFrameRange.count(), inAudioSystem, inOptionFlags,
359  inNumChannels, inFrameRange.firstFrame(), inFrameRange.lastFrame())
360  : false;
361 }
362 
363 
365  const UWord inFrameCount,
366  const NTV2AudioSystem inAudioSystem,
367  const ULWord inOptionFlags,
368  const UByte inNumChannels,
369  const UWord inStartFrameNumber,
370  const UWord inEndFrameNumber)
371 {
372  if (!NTV2_IS_VALID_CHANNEL(inChannel))
373  {ACFAIL(GetDescription() << ": Ch" << DEC(inChannel+1) << " is illegal channel value"); return false;} // Must be valid channel
374  if (!inNumChannels || inNumChannels > 8)
375  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": illegal 'inNumChannels' value '" << DEC(inNumChannels) << "' -- must be 1-8"); return false;} // At least one channel
376  if (!gFBAllocLock.IsValid())
377  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": FBAllocLock mutex not ready"); return false;} // Mutex not ready
378 
379  AJAAutoLock autoLock (&gFBAllocLock); // Avoid AutoCirculate buffer collisions
380  LWord startFrameNumber(LWord(inStartFrameNumber+0));
381  LWord endFrameNumber (LWord(inEndFrameNumber+0));
382  if (!endFrameNumber && !startFrameNumber)
383  {
384  if (!inFrameCount)
385  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": Zero frames requested"); return false;}
386  if (!FindUnallocatedFrames (inFrameCount, startFrameNumber, endFrameNumber, inChannel))
387  return false;
388  }
389  else if (inFrameCount)
390  ACWARN (GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": FrameCount " << DEC(inFrameCount) << " ignored -- using start/end "
391  << DEC(inStartFrameNumber) << "/" << DEC(inEndFrameNumber) << " frame numbers");
392  if (endFrameNumber < startFrameNumber) // endFrame must be > startFrame
393  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": EndFrame(" << DEC(endFrameNumber) << ") precedes StartFrame("
394  << DEC(startFrameNumber) << ")"); return false;}
395  if ((endFrameNumber - startFrameNumber + 1) < 2) // must be at least 2 frames
396  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": Frames " << DEC(startFrameNumber) << "-" << DEC(endFrameNumber) << " < 2 frames"); return false;}
397  if (startFrameNumber >= MAX_FRAMEBUFFERS)
398  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": Start frame " << DEC(startFrameNumber) << " exceeds max " << DEC(MAX_FRAMEBUFFERS-1)); return false;}
399  if (endFrameNumber >= MAX_FRAMEBUFFERS)
400  {ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": End frame " << DEC(endFrameNumber) << " exceeds max " << DEC(MAX_FRAMEBUFFERS-1)); return false;}
402  ACWARN(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": MultiLink Audio requested, but device doesn't support it");
403  const UWord numAudSystems(UWord(GetNumSupported(kDeviceGetNumAudioSystems))); // AutoCirc cannot use AudioMixer or HostAudio
404  if (inAudioSystem != NTV2_AUDIOSYSTEM_INVALID)
405  {
406  if (numAudSystems && UWord(inAudioSystem) >= numAudSystems)
407  {ACFAIL(GetDescription() << ": Invalid audio system specified: AudSys" << DEC(inAudioSystem+1) << " -- exceeds max legal AudSys" << DEC(numAudSystems)); return false;}
408  }
409 
410  // Warn about "with anc" and VANC mode...
411  if (inOptionFlags & AUTOCIRCULATE_WITH_ANC)
412  {
414  if (GetVANCMode(vancMode, inChannel) && NTV2_IS_VANCMODE_ON(vancMode))
415  ACWARN(GetDescription() << ": Output Ch" << DEC(inChannel+1) << "AUTOCIRCULATE_WITH_ANC set, but also has "
416  << ::NTV2VANCModeToString(vancMode) << " set -- this may cause anc insertion problems");
417  }
418 
419  // Fill in our OS independent data structure...
421  autoCircData.lVal1 = startFrameNumber;
422  autoCircData.lVal2 = endFrameNumber;
423  autoCircData.lVal3 = inAudioSystem;
424  if (inOptionFlags & AUTOCIRCULATE_WITH_MULTILINK_AUDIO1)
425  autoCircData.lVal3 |= NTV2_AUDIOSYSTEM_Plus1;
426  if (inOptionFlags & AUTOCIRCULATE_WITH_MULTILINK_AUDIO2)
427  autoCircData.lVal3 |= NTV2_AUDIOSYSTEM_Plus2;
428  if (inOptionFlags & AUTOCIRCULATE_WITH_MULTILINK_AUDIO3)
429  autoCircData.lVal3 |= NTV2_AUDIOSYSTEM_Plus3;
430  autoCircData.lVal4 = inNumChannels;
431  if (inOptionFlags & AUTOCIRCULATE_WITH_FIELDS)
432  autoCircData.lVal6 |= AUTOCIRCULATE_WITH_FIELDS;
433  if (inOptionFlags & AUTOCIRCULATE_WITH_HDMIAUX)
434  autoCircData.lVal6 |= AUTOCIRCULATE_WITH_HDMIAUX;
435  if (inOptionFlags & AUTOCIRCULATE_WITH_AUDIO_CONTROL)
436  autoCircData.bVal1 = false;
437  else
438  autoCircData.bVal1 = NTV2_IS_VALID_AUDIO_SYSTEM(inAudioSystem) ? true : false;
439  autoCircData.bVal2 = (inOptionFlags & AUTOCIRCULATE_WITH_RP188) ? true : false;
440  autoCircData.bVal3 = (inOptionFlags & AUTOCIRCULATE_WITH_FBFCHANGE) ? true : false;
441  autoCircData.bVal4 = (inOptionFlags & AUTOCIRCULATE_WITH_FBOCHANGE) ? true : false;
442  autoCircData.bVal5 = (inOptionFlags & AUTOCIRCULATE_WITH_COLORCORRECT) ? true : false;
443  autoCircData.bVal6 = (inOptionFlags & AUTOCIRCULATE_WITH_VIDPROC) ? true : false;
444  autoCircData.bVal7 = (inOptionFlags & AUTOCIRCULATE_WITH_ANC) ? true : false;
445  autoCircData.bVal8 = (inOptionFlags & AUTOCIRCULATE_WITH_LTC) ? true : false;
446  if (IsSupported(kDeviceCanDo2110)) // If S2110 IP device...
447  if (inOptionFlags & AUTOCIRCULATE_WITH_RP188) // and caller wants RP188
448  if (!(inOptionFlags & AUTOCIRCULATE_WITH_ANC)) // but caller failed to enable Anc playout
449  {
450  autoCircData.bVal7 = true; // Enable Anc insertion anyway
451  ACWARN(GetDescription() << ": Output Ch" << DEC(inChannel+1)
452  << ": AUTOCIRCULATE_WITH_RP188 requested without AUTOCIRCULATE_WITH_ANC -- enabled AUTOCIRCULATE_WITH_ANC anyway");
453  }
454 
455  const bool result (AutoCirculate(autoCircData)); // Call the OS-specific method
456  if (result)
457  { // Success!
458  #if 1
459  // Warn about interference from other channels...
460  ULWordSequence badRgns;
461  SDRAMAuditor auditor(*this);
462  auditor.GetBadRegions(badRgns);
463  for (size_t ndx(0); ndx < badRgns.size(); ndx++)
464  { const ULWord rgnInfo(badRgns.at(ndx));
465  const UWord startBlk(rgnInfo >> 16), numBlks(UWord(rgnInfo & 0x0000FFFF));
466  NTV2StringSet tags;
467  auditor.GetTagsForFrameIndex (startBlk, tags);
468  const string infoStr (aja::join(tags, ", "));
469  ostringstream acLabel; acLabel << "AC" << DEC(inChannel+1); // Search for label e.g. "AC2"
470  if (infoStr.find(acLabel.str()) != string::npos)
471  { ostringstream warning;
472  if (numBlks > 1)
473  warning << "Frms " << DEC0N(startBlk,3) << "-" << DEC0N(startBlk+numBlks-1,3);
474  else
475  warning << "Frm " << DEC0N(startBlk,3);
476  ACWARN(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": memory overlap/interference: " << warning.str() << ": " << infoStr);
477  }
478  } // for each "bad" region
479  #endif
480  #if 1
481  { AUTOCIRCULATE_STATUS stat;
482  if (AutoCirculateGetStatus (inChannel, stat) && !stat.IsStopped() && stat.WithAudio())
483  { // Not stopped and AutoCirculating audio -- check if audio buffer capacity will be exceeded...
484  ULWord audChlsPerSample(0);
487  GetNumberAudioChannels (audChlsPerSample, stat.GetAudioSystem());
488  if (GetFrameRate (fr, inChannel) && NTV2_IS_SUPPORTED_NTV2FrameRate(fr))
489  if (GetAudioRate (ar, stat.GetAudioSystem()) && NTV2_IS_VALID_AUDIO_RATE(ar))
490  {
491  const double framesPerSecond (double(::GetScaleFromFrameRate(fr)) / 100.00);
492  const double samplesPerSecond (double(::GetAudioSamplesPerSecond(ar)));
493  const double bytesPerChannel (4.0);
494  const double channelsPerSample (double(audChlsPerSample+0));
495  const double bytesPerFrame (samplesPerSecond * bytesPerChannel * channelsPerSample / framesPerSecond);
496  const ULWord maxVideoFrames (4UL * 1024UL * 1024UL / ULWord(bytesPerFrame));
497  if (stat.GetFrameCount() > maxVideoFrames)
498  ACWARN(GetDescription() << ": Output Ch" << DEC(inChannel+1) << ": " << DEC(stat.GetFrameCount()) << " frames ("
499  << DEC(stat.GetStartFrame()) << "-" << DEC(stat.GetEndFrame()) << ") exceeds "
500  << DEC(maxVideoFrames) << "-frame max buffer capacity of AudSys" << DEC(stat.GetAudioSystem()+1));
501  }
502  }
503  }
504  #endif
505  ACINFO(GetDescription() << ": Output Ch" << DEC(inChannel+1) << " initialized using frames " << DEC(startFrameNumber) << "-" << DEC(endFrameNumber));
506  }
507  else
508  ACFAIL(GetDescription() << ": Output Ch" << DEC(inChannel+1) << " initialization failed");
509  return result;
510 
511 } // AutoCirculateInitForOutput
512 
514  const NTV2ACFrameRange & inFrameRange,
515  const NTV2AudioSystem inAudioSystem,
516  const ULWord inOptionFlags,
517  const UByte inNumChannels)
518 {
519  return inFrameRange ? AutoCirculateInitForOutput (inChannel, inFrameRange.count(), inAudioSystem, inOptionFlags,
520  inNumChannels, inFrameRange.firstFrame(), inFrameRange.lastFrame())
521  : false;
522 }
523 
524 
525 bool CNTV2Card::AutoCirculateStart (const NTV2Channel inChannel, const ULWord64 inStartTime)
526 {
527  AUTOCIRCULATE_DATA autoCircData (inStartTime ? eStartAutoCircAtTime : eStartAutoCirc);
528  autoCircData.lVal1 = LWord(inStartTime >> 32);
529  autoCircData.lVal2 = LWord(inStartTime & 0xFFFFFFFF);
530  if (!GetCurrentACChannelCrosspoint (*this, inChannel, autoCircData.channelSpec))
531  return false;
532  const bool result (AutoCirculate(autoCircData));
533  if (result)
534  ACINFO(GetDescription() << ": Started Ch" << DEC(inChannel+1));
535  else
536  ACFAIL(GetDescription() << ": Failed to start Ch" << DEC(inChannel+1));
537  return result;
538 }
539 
540 
541 bool CNTV2Card::AutoCirculateStop (const NTV2Channel inChannel, const bool inAbort)
542 {
543  if (!NTV2_IS_VALID_CHANNEL (inChannel))
544  return false;
545 
546  const AUTO_CIRC_COMMAND acCommand (inAbort ? eAbortAutoCirc : eStopAutoCirc);
547  AUTOCIRCULATE_DATA stopInput (acCommand, ::NTV2ChannelToInputCrosspoint (inChannel));
548  AUTOCIRCULATE_DATA stopOutput (acCommand, ::NTV2ChannelToOutputCrosspoint (inChannel));
550  AUTOCIRCULATE_STATUS acStatus;
551 
552  // Stop input or output A/C using the old driver call...
553  const bool stopInputFailed (!AutoCirculate (stopInput));
554  const bool stopOutputFailed (!AutoCirculate (stopOutput));
555  if (stopInputFailed && stopOutputFailed)
556  {
557  ACFAIL(GetDescription() << ": Failed to stop Ch" << DEC(inChannel+1));
558  return false; // Both failed
559  }
560  if (inAbort)
561  {
562  ACINFO(GetDescription() << ": Aborted Ch" << DEC(inChannel+1));
563  return true; // In abort case, no more to do!
564  }
565 
566  // Wait until driver changes AC state to DISABLED...
567  bool result (GetMode(inChannel, mode));
568  if (NTV2_IS_INPUT_MODE(mode))
569  WaitForInputFieldID(NTV2_FIELD0, inChannel);
570  if (NTV2_IS_OUTPUT_MODE(mode))
571  WaitForOutputFieldID(NTV2_FIELD0, inChannel);
572  if (AutoCirculateGetStatus(inChannel, acStatus) && acStatus.acState != NTV2_AUTOCIRCULATE_DISABLED)
573  {
574  ACWARN(GetDescription() << ": Failed to stop Ch" << DEC(inChannel+1) << " -- retrying with ABORT");
575  return AutoCirculateStop(inChannel, true); // something's wrong -- abort (WARNING: RECURSIVE CALL!)
576  }
577  ACINFO(GetDescription() << ": Stopped Ch" << DEC(inChannel+1));
578  return result;
579 
580 } // AutoCirculateStop
581 
582 
583 bool CNTV2Card::AutoCirculateStop (const NTV2ChannelSet & inChannels, const bool inAbort)
584 { UWord failures(0);
585  for (NTV2ChannelSetConstIter it(inChannels.begin()); it != inChannels.end(); ++it)
586  if (!AutoCirculateStop(*it, inAbort))
587  failures++;
588  return !failures;
589 }
590 
591 
592 bool CNTV2Card::AutoCirculatePause (const NTV2Channel inChannel, const UWord inAtFrameNum)
593 { (void) inAtFrameNum;
594  // Use the old A/C driver call...
595  AUTOCIRCULATE_DATA autoCircData (ePauseAutoCirc);
596  autoCircData.bVal1 = false;
597  if (!GetCurrentACChannelCrosspoint (*this, inChannel, autoCircData.channelSpec))
598  return false;
599 
600  // FUTURE: pass inAtFrameNum
601  // if (inAtFrameNum != 0xFFFF)
602  // autoCircData.lVal6 = LWord(inAtFrameNum);
603  const bool result(AutoCirculate(autoCircData));
604  if (result)
605  ACINFO(GetDescription() << ": Paused Ch" << DEC(inChannel+1));
606  else
607  ACFAIL(GetDescription() << ": Failed to pause Ch" << DEC(inChannel+1));
608  return result;
609 
610 } // AutoCirculatePause
611 
612 
613 bool CNTV2Card::AutoCirculateResume (const NTV2Channel inChannel, const bool inClearDropCount)
614 {
615  // Use the old A/C driver call...
616  AUTOCIRCULATE_DATA autoCircData (ePauseAutoCirc);
617  autoCircData.bVal1 = true;
618  autoCircData.bVal2 = inClearDropCount;
619  if (!GetCurrentACChannelCrosspoint (*this, inChannel, autoCircData.channelSpec))
620  return false;
621 
622  const bool result(AutoCirculate(autoCircData));
623  if (result)
624  ACINFO(GetDescription() << ": Resumed Ch" << DEC(inChannel+1));
625  else
626  ACFAIL(GetDescription() << ": Failed to resume Ch" << DEC(inChannel+1));
627  return result;
628 
629 } // AutoCirculateResume
630 
631 
632 bool CNTV2Card::AutoCirculateFlush (const NTV2Channel inChannel, const bool inClearDropCount)
633 {
634  // Use the old A/C driver call...
636  autoCircData.bVal1 = inClearDropCount;
637  if (!GetCurrentACChannelCrosspoint (*this, inChannel, autoCircData.channelSpec))
638  return false;
639 
640  const bool result(AutoCirculate(autoCircData));
641  if (result)
642  ACINFO(GetDescription() << ": Flushed Ch" << DEC(inChannel+1) << ", " << (inClearDropCount?"cleared":"retained") << " drop count");
643  else
644  ACFAIL(GetDescription() << ": Failed to flush Ch" << DEC(inChannel+1));
645  return result;
646 
647 } // AutoCirculateFlush
648 
649 
650 bool CNTV2Card::AutoCirculatePreRoll (const NTV2Channel inChannel, const ULWord inPreRollFrames)
651 {
652  // Use the old A/C driver call...
654  autoCircData.lVal1 = LWord(inPreRollFrames);
655  if (!GetCurrentACChannelCrosspoint (*this, inChannel, autoCircData.channelSpec))
656  return false;
657 
658  const bool result(AutoCirculate(autoCircData));
659  if (result)
660  ACINFO(GetDescription() << ": Prerolled " << DEC(inPreRollFrames) << " frame(s) on Ch" << DEC(inChannel+1));
661  else
662  ACFAIL(GetDescription() << ": Failed to preroll " << DEC(inPreRollFrames) << " frame(s) on Ch" << DEC(inChannel+1));
663  return result;
664 
665 } // AutoCirculatePreRoll
666 
667 
669 {
670  outStatus.Clear ();
671  if (!GetCurrentACChannelCrosspoint (*this, inChannel, outStatus.acCrosspoint))
672  return false;
673 
675  {
676  const AUTOCIRCULATE_STATUS notRunningStatus (::NTV2ChannelToOutputCrosspoint (inChannel));
677  outStatus = notRunningStatus;
678  return true; // AutoCirculate not running on this channel
679  }
680 
681  const bool result(NTV2Message(outStatus));
682  if (!result)
683  ACFAIL(GetDescription() << ": Failed to get status on Ch" << DEC(inChannel+1));
684  return result;
685 
686 } // AutoCirculateGetStatus
687 
688 
689 bool CNTV2Card::AutoCirculateGetFrameStamp (const NTV2Channel inChannel, const ULWord inFrameNum, FRAME_STAMP & outFrameStamp)
690 {
691  // Use the new driver call...
692  outFrameStamp.acFrameTime = LWord64 (inChannel);
693  outFrameStamp.acRequestedFrame = inFrameNum;
694  return NTV2Message(outFrameStamp);
695 
696 } // AutoCirculateGetFrameStamp
697 
698 
699 bool CNTV2Card::AutoCirculateSetActiveFrame (const NTV2Channel inChannel, const ULWord inNewActiveFrame)
700 {
701  // Use the old A/C driver call...
702  AUTOCIRCULATE_DATA autoCircData (eSetActiveFrame);
703  autoCircData.lVal1 = LWord(inNewActiveFrame);
704  if (!GetCurrentACChannelCrosspoint (*this, inChannel, autoCircData.channelSpec))
705  return false;
706 
707  const bool result(AutoCirculate(autoCircData));
708  if (result)
709  ACINFO(GetDescription() << ": Set active frame to " << DEC(inNewActiveFrame) << " on Ch" << DEC(inChannel+1));
710  else
711  ACFAIL(GetDescription() << ": Failed to set active frame to " << DEC(inNewActiveFrame) << " on Ch" << DEC(inChannel+1));
712  return result;
713 
714 } // AutoCirculateSetActiveFrame
715 
716 
718 {
719  if (!_boardOpened)
720  return false;
721  #if defined(_DEBUG)
722  NTV2_ASSERT (inOutXferInfo.NTV2_IS_STRUCT_VALID ());
723  #endif
724 
726  NTV2TaskMode taskMode (NTV2_OEM_TASKS);
727  if (!GetCurrentACChannelCrosspoint (*this, inChannel, crosspoint))
728  return false;
729  if (!NTV2_IS_VALID_NTV2CROSSPOINT(crosspoint))
730  return false;
731  GetTaskMode(taskMode);
732 
733  if (NTV2_IS_INPUT_CROSSPOINT(crosspoint))
734  inOutXferInfo.acTransferStatus.acFrameStamp.acTimeCodes.Fill(ULWord(0xFFFFFFFF)); // Invalidate old timecodes
735  else if (NTV2_IS_OUTPUT_CROSSPOINT(crosspoint))
736  {
737  bool isProgressive (false);
738  IsProgressiveStandard(isProgressive, inChannel);
739  if (inOutXferInfo.acRP188.IsValid())
740  inOutXferInfo.SetAllOutputTimeCodes(inOutXferInfo.acRP188, /*alsoSetF2*/!isProgressive);
741 
742  const NTV2_RP188 * pArray (reinterpret_cast <const NTV2_RP188*>(inOutXferInfo.acOutputTimeCodes.GetHostPointer()));
743  if (pArray && pArray[NTV2_TCINDEX_DEFAULT].IsValid())
744  inOutXferInfo.SetAllOutputTimeCodes(pArray[NTV2_TCINDEX_DEFAULT], /*alsoSetF2*/!isProgressive);
745  }
746 
747  bool tmpLocalF1AncBuffer(false), tmpLocalF2AncBuffer(false);
748  NTV2Buffer savedAncF1, savedAncF2;
749  if (IsSupported(kDeviceCanDo2110) && NTV2_IS_OUTPUT_CROSSPOINT(crosspoint))
750  {
751  // S2110 Playout: So that most Retail & OEM playout apps "just work" with S2110 RTP Anc streams,
752  // our classic SDI Anc data that device firmware normally embeds into SDI output
753  // as derived from registers -- VPID & RP188 -- the SDK here automatically inserts
754  // these packets into the outgoing RTP streams, even if the client didn't provide
755  // Anc buffers in the AUTOCIRCULATE_TRANSFER object, or specify AUTOCIRCULATE_WITH_ANC.
756  ULWord F1OffsetFromBottom(0), F2OffsetFromBottom(0);
757  size_t F1SizeInBytes(0), F2SizeInBytes(0);
758  if (GetAncRegionOffsetFromBottom(F1OffsetFromBottom, NTV2_AncRgn_Field1)
759  && GetAncRegionOffsetFromBottom(F2OffsetFromBottom, NTV2_AncRgn_Field2))
760  {
761  F2SizeInBytes = size_t(F2OffsetFromBottom);
762  if (F2OffsetFromBottom < F1OffsetFromBottom)
763  F1SizeInBytes = size_t(F1OffsetFromBottom - F2OffsetFromBottom);
764  else
765  F1SizeInBytes = size_t(F2OffsetFromBottom - F1OffsetFromBottom);
766  }
767  if ((_boardID == DEVICE_ID_IOIP_2110) || (_boardID == DEVICE_ID_IOIP_2110_RGB12))
768  { // IoIP 2110 Playout requires room for RTP+GUMP per anc buffer, to also operate SDI5 Mon output
769  ULWord F1MonOffsetFromBottom(0), F2MonOffsetFromBottom(0);
770  const bool good (GetAncRegionOffsetFromBottom(F1MonOffsetFromBottom, NTV2_AncRgn_MonField1)
771  && GetAncRegionOffsetFromBottom(F2MonOffsetFromBottom, NTV2_AncRgn_MonField2));
772  if (good // Driver expects anc regions in this order (from bottom): F2Mon, F2, F1Mon, F1
773  && F2MonOffsetFromBottom < F2OffsetFromBottom
774  && F2OffsetFromBottom < F1MonOffsetFromBottom
775  && F1MonOffsetFromBottom < F1OffsetFromBottom)
776  {
777  F1SizeInBytes = size_t(F1OffsetFromBottom - F2OffsetFromBottom);
778  F2SizeInBytes = size_t(F2OffsetFromBottom);
779  }
780  else
781  { // Anc regions out of order!
782  XMTWARN(GetDescription() << ": IoIP 2110 playout anc rgns disordered (offsets from bottom): F2Mon=" << HEX0N(F2MonOffsetFromBottom,8)
783  << " F2=" << HEX0N(F2OffsetFromBottom,8) << " F1Mon=" << HEX0N(F1MonOffsetFromBottom,8)
784  << " F1=" << HEX0N(F1OffsetFromBottom,8));
785  F1SizeInBytes = F2SizeInBytes = 0; // Out of order, don't do Anc
786  }
787  savedAncF1 = inOutXferInfo.acANCBuffer; // copy
788  savedAncF2 = inOutXferInfo.acANCField2Buffer; // copy
789  if (inOutXferInfo.acANCBuffer.GetByteCount() < F1SizeInBytes)
790  { // Enlarge acANCBuffer, and copy everything from savedAncF1 into it...
791  inOutXferInfo.acANCBuffer.Allocate(F1SizeInBytes);
792  inOutXferInfo.acANCBuffer.Fill(uint64_t(0));
793  inOutXferInfo.acANCBuffer.CopyFrom(savedAncF1, 0, 0, savedAncF1.GetByteCount());
794  }
795  if (inOutXferInfo.acANCField2Buffer.GetByteCount() < F2SizeInBytes)
796  { // Enlarge acANCField2Buffer, and copy everything from savedAncF2 into it...
797  inOutXferInfo.acANCField2Buffer.Allocate(F2SizeInBytes);
798  inOutXferInfo.acANCField2Buffer.Fill(uint64_t(0));
799  inOutXferInfo.acANCField2Buffer.CopyFrom(savedAncF2, 0, 0, savedAncF2.GetByteCount());
800  }
801  } // if IoIP 2110 playout
802  else
803  { // else KonaIP 2110 playout
804  if (inOutXferInfo.acANCBuffer.IsNULL())
805  tmpLocalF1AncBuffer = inOutXferInfo.acANCBuffer.Allocate(F1SizeInBytes);
806  else
807  savedAncF1 = inOutXferInfo.acANCBuffer; // copy
808  if (inOutXferInfo.acANCField2Buffer.IsNULL())
809  tmpLocalF2AncBuffer = inOutXferInfo.acANCField2Buffer.Allocate(F2SizeInBytes);
810  else
811  savedAncF2 = inOutXferInfo.acANCField2Buffer; // copy
812  } // else KonaIP 2110 playout
813  S2110DeviceAncToXferBuffers(inChannel, inOutXferInfo);
814  } // if SMPTE 2110 playout
815  else if (IsSupported(kDeviceCanDo2110) && NTV2_IS_INPUT_CROSSPOINT(crosspoint))
816  { // Need local host buffers to receive 2110 Anc VPID & ATC
817  if (inOutXferInfo.acANCBuffer.IsNULL())
818  tmpLocalF1AncBuffer = inOutXferInfo.acANCBuffer.Allocate(2048);
819  if (inOutXferInfo.acANCField2Buffer.IsNULL())
820  tmpLocalF2AncBuffer = inOutXferInfo.acANCField2Buffer.Allocate(2048);
821  } // if SMPTE 2110 capture
822 
824  // Call the driver...
825  inOutXferInfo.acCrosspoint = crosspoint;
826  bool result = NTV2Message(inOutXferInfo);
828 
829  if (result && NTV2_IS_INPUT_CROSSPOINT(crosspoint))
830  {
831  if (IsSupported(kDeviceCanDo2110))
832  { // S2110: decode VPID and timecode anc packets from RTP, and put into A/C Xfer and device regs
833  S2110DeviceAncFromXferBuffers(inChannel, inOutXferInfo);
834  }
835  if (taskMode == NTV2_STANDARD_TASKS)
836  {
837  // After 12.? shipped, we discovered problems with timecode capture in our classic retail stuff.
838  // The acTimeCodes[NTV2_TCINDEX_DEFAULT] was coming up empty.
839  // Rather than fix all three drivers -- the Right, but Difficult Thing To Do --
840  // we decided to do the Easy Thing, here, in user-space.
841 
842  // First, determine the ControlPanel's current Input source (SDIIn1/HDMIIn1 or SDIIn2/HDMIIn2)...
843  ULWord inputSelect (NTV2_Input1Select);
844  ReadRegister (kVRegInputSelect, inputSelect);
845  const bool bIsInput2 (inputSelect == NTV2_Input2Select);
846 
847  // Next, determine the ControlPanel's current TimeCode source (LTC? VITC1? VITC2)...
850 
851  // Now convert that into an NTV2TCIndex...
852  NTV2TCIndex TimecodeIndex = NTV2_TCINDEX_DEFAULT;
853  switch (TimecodeSource)
854  {
855  default:/*kRP188SourceEmbeddedLTC:*/TimecodeIndex = bIsInput2 ? NTV2_TCINDEX_SDI2_LTC : NTV2_TCINDEX_SDI1_LTC; break;
856  case kRP188SourceEmbeddedVITC1: TimecodeIndex = bIsInput2 ? NTV2_TCINDEX_SDI2 : NTV2_TCINDEX_SDI1; break;
857  case kRP188SourceEmbeddedVITC2: TimecodeIndex = bIsInput2 ? NTV2_TCINDEX_SDI2_2 : NTV2_TCINDEX_SDI1_2; break;
858  case kRP188SourceLTCPort: TimecodeIndex = NTV2_TCINDEX_LTC1; break;
859  }
860 
861  // Fetch the TimeCode value that's in that NTV2TCIndex slot...
862  NTV2_RP188 tcValue;
863  inOutXferInfo.GetInputTimeCode(tcValue, TimecodeIndex);
864  if (TimecodeIndex == NTV2_TCINDEX_LTC1)
865  { // Special case for external LTC:
866  // Our driver currently returns all-zero DBB values for external LTC.
867  // It should probably at least set DBB BIT(17) "selected RP188 received" if external LTC is present.
868  // Ticket 3367: Our QuickTime 'vdig' relies on DBB BIT(17) being set, or it assumes timecode is invalid
869  if (tcValue.fLo && tcValue.fHi && tcValue.fLo != 0xFFFFFFFF && tcValue.fHi != 0xFFFFFFFF)
870  tcValue.fDBB |= 0x00020000;
871  }
872 
873  // Valid or not, stuff that TimeCode value into inOutXferInfo.acTransferStatus.acFrameStamp.acTimeCodes[NTV2_TCINDEX_DEFAULT]...
874  NTV2_RP188 * pArray (reinterpret_cast <NTV2_RP188 *> (inOutXferInfo.acTransferStatus.acFrameStamp.acTimeCodes.GetHostPointer()));
875  if (pArray)
876  pArray [NTV2_TCINDEX_DEFAULT] = tcValue;
877  } // if retail mode
878  } // if NTV2Message OK && capturing
879  if (result && NTV2_IS_OUTPUT_CROSSPOINT(crosspoint))
880  {
881  if (savedAncF1)
882  inOutXferInfo.acANCBuffer = savedAncF1; // restore
883  if (savedAncF2)
884  inOutXferInfo.acANCField2Buffer = savedAncF2; // restore
885  } // if successful playout
886 
887  if (tmpLocalF1AncBuffer)
888  inOutXferInfo.acANCBuffer.Deallocate();
889  if (tmpLocalF2AncBuffer)
890  inOutXferInfo.acANCField2Buffer.Deallocate();
891 
892  #if defined (AJA_NTV2_CLEAR_DEVICE_ANC_BUFFER_AFTER_CAPTURE_XFER)
893  if (result && NTV2_IS_INPUT_CROSSPOINT(crosspoint))
894  {
895  ULWord doZeroing (0);
896  if (ReadRegister(kVRegZeroDeviceAncPostCapture, doZeroing) && doZeroing)
897  { // Zero out the Anc buffer on the device...
898  static NTV2Buffer gClearDeviceAncBuffer;
899  const LWord xferFrame (inOutXferInfo.GetTransferFrameNumber());
900  ULWord ancOffsetF1 (0);
901  ULWord ancOffsetF2 (0);
903  ReadRegister(kVRegAncField1Offset, ancOffsetF1);
904  ReadRegister(kVRegAncField2Offset, ancOffsetF2);
905  GetFrameBufferSize(inChannel, fbSize);
906  const ULWord fbByteCount (::NTV2FramesizeToByteCount(fbSize));
907  const ULWord ancOffset (ancOffsetF2 > ancOffsetF1 ? ancOffsetF2 : ancOffsetF1); // Use whichever is larger
908  NTV2_ASSERT (xferFrame != -1);
909  if (gClearDeviceAncBuffer.IsNULL() || (gClearDeviceAncBuffer.GetByteCount() != ancOffset))
910  {
911  gClearDeviceAncBuffer.Allocate(ancOffset); // Allocate it
912  gClearDeviceAncBuffer.Fill (ULWord(0)); // Clear it
913  }
914  if (xferFrame != -1 && fbByteCount && !gClearDeviceAncBuffer.IsNULL())
915  DMAWriteSegments (ULWord(xferFrame),
916  reinterpret_cast<ULWord*>(gClearDeviceAncBuffer.GetHostPointer()), // host buffer
917  fbByteCount - ancOffset, // device memory offset, in bytes
918  gClearDeviceAncBuffer.GetByteCount(), // total number of bytes to xfer
919  1, // numSegments -- one chunk of 'ancOffset'
920  gClearDeviceAncBuffer.GetByteCount(), // segmentHostPitch
921  gClearDeviceAncBuffer.GetByteCount()); // segmentCardPitch
922  }
923  }
924  #endif // AJA_NTV2_CLEAR_DEVICE_ANC_BUFFER_AFTER_CAPTURE_XFER
925 
926  #if defined (AJA_NTV2_CLEAR_HOST_ANC_BUFFER_TAIL_AFTER_CAPTURE_XFER)
927  if (result && NTV2_IS_INPUT_CROSSPOINT(crosspoint))
928  {
929  ULWord doZeroing (0);
930  if (ReadRegister(kVRegZeroHostAncPostCapture, doZeroing) && doZeroing)
931  { // Zero out everything past the last captured Anc byte in the client's host buffer(s)...
932  NTV2Buffer & clientAncBufferF1 (inOutXferInfo.acANCBuffer);
933  NTV2Buffer & clientAncBufferF2 (inOutXferInfo.acANCField2Buffer);
934  const ULWord ancF1ByteCount (inOutXferInfo.GetCapturedAncByteCount(false));
935  const ULWord ancF2ByteCount (inOutXferInfo.GetCapturedAncByteCount(true));
936  void * pF1TailEnd (clientAncBufferF1.GetHostAddress(ancF1ByteCount));
937  void * pF2TailEnd (clientAncBufferF2.GetHostAddress(ancF2ByteCount));
938  if (pF1TailEnd && clientAncBufferF1.GetByteCount() > ancF1ByteCount)
939  ::memset (pF1TailEnd, 0, clientAncBufferF1.GetByteCount() - ancF1ByteCount);
940  if (pF2TailEnd && clientAncBufferF2.GetByteCount() > ancF2ByteCount)
941  ::memset (pF2TailEnd, 0, clientAncBufferF2.GetByteCount() - ancF2ByteCount);
942  }
943  }
944  #endif // AJA_NTV2_CLEAR_HOST_ANC_BUFFER_TAIL_AFTER_CAPTURE_XFER
945 
946  if (result)
947  ACDBG(GetDescription() << ": Transfer successful for Ch" << DEC(inChannel+1));
948  else
949  ACFAIL(GetDescription() << ": Transfer failed on Ch" << DEC(inChannel+1));
950  return result;
951 
952 } // AutoCirculateTransfer
953 
954 
955 static const AJA_FrameRate sNTV2Rate2AJARate[] = { AJA_FrameRate_Unknown // NTV2_FRAMERATE_UNKNOWN = 0,
956  ,AJA_FrameRate_6000 // NTV2_FRAMERATE_6000 = 1,
957  ,AJA_FrameRate_5994 // NTV2_FRAMERATE_5994 = 2,
958  ,AJA_FrameRate_3000 // NTV2_FRAMERATE_3000 = 3,
959  ,AJA_FrameRate_2997 // NTV2_FRAMERATE_2997 = 4,
960  ,AJA_FrameRate_2500 // NTV2_FRAMERATE_2500 = 5,
961  ,AJA_FrameRate_2400 // NTV2_FRAMERATE_2400 = 6,
962  ,AJA_FrameRate_2398 // NTV2_FRAMERATE_2398 = 7,
963  ,AJA_FrameRate_5000 // NTV2_FRAMERATE_5000 = 8,
964  ,AJA_FrameRate_4800 // NTV2_FRAMERATE_4800 = 9,
965  ,AJA_FrameRate_4795 // NTV2_FRAMERATE_4795 = 10,
966  ,AJA_FrameRate_12000 // NTV2_FRAMERATE_12000 = 11,
967  ,AJA_FrameRate_11988 // NTV2_FRAMERATE_11988 = 12,
968  ,AJA_FrameRate_1500 // NTV2_FRAMERATE_1500 = 13,
969  ,AJA_FrameRate_1498 // NTV2_FRAMERATE_1498 = 14,
970 #if !defined(NTV2_DEPRECATE_16_0)
971  ,AJA_FrameRate_1900 // NTV2_FRAMERATE_1900 = 15, // Formerly 09 in older SDKs
972  ,AJA_FrameRate_1898 // NTV2_FRAMERATE_1898 = 16, // Formerly 10 in older SDKs
973  ,AJA_FrameRate_1800 // NTV2_FRAMERATE_1800 = 17, // Formerly 11 in older SDKs
974  ,AJA_FrameRate_1798 // NTV2_FRAMERATE_1798 = 18, // Formerly 12 in older SDKs
975 #endif // !defined(NTV2_DEPRECATE_16_0)
976  };
977 
978 static const TimecodeFormat sNTV2Rate2TCFormat[] = {kTCFormatUnknown // NTV2_FRAMERATE_UNKNOWN = 0,
979  ,kTCFormat60fps // NTV2_FRAMERATE_6000 = 1,
980  ,kTCFormat30fps // NTV2_FRAMERATE_5994 = 2,
981  ,kTCFormat30fps // NTV2_FRAMERATE_3000 = 3,
982  ,kTCFormat30fps // NTV2_FRAMERATE_2997 = 4,
983  ,kTCFormat25fps // NTV2_FRAMERATE_2500 = 5,
984  ,kTCFormat24fps // NTV2_FRAMERATE_2400 = 6,
985  ,kTCFormat24fps // NTV2_FRAMERATE_2398 = 7,
986  ,kTCFormat50fps // NTV2_FRAMERATE_5000 = 8,
987  ,kTCFormat48fps // NTV2_FRAMERATE_4800 = 9,
988  ,kTCFormat48fps // NTV2_FRAMERATE_4795 = 10,
989  ,kTCFormat60fps // NTV2_FRAMERATE_12000 = 11,
990  ,kTCFormat60fps // NTV2_FRAMERATE_11988 = 12,
991  ,kTCFormat30fps // NTV2_FRAMERATE_1500 = 13,
992  ,kTCFormat30fps // NTV2_FRAMERATE_1498 = 14,
993 #if !defined(NTV2_DEPRECATE_16_0)
994  ,kTCFormatUnknown // NTV2_FRAMERATE_1900 = 15,
995  ,kTCFormatUnknown // NTV2_FRAMERATE_1898 = 16,
996  ,kTCFormatUnknown // NTV2_FRAMERATE_1800 = 17,
997  ,kTCFormatUnknown // NTV2_FRAMERATE_1798 = 18,
998 #endif // !defined(NTV2_DEPRECATE_16_0)
999  };
1000 
1001 // VPID Packet Insertion 1080 720 525 625 1080p 2K 2K1080p 2K1080i UHD 4K UHDHFR 4KHFR
1002 static const uint16_t sVPIDLineNumsF1[] = { 10, 10, 13, 9, 10, 10, 10, 10, 10, 10, 10, 10 };
1003 static const uint16_t sVPIDLineNumsF2[] = { 572, 0, 276, 322, 0, 0, 0, 572, 0, 0, 0, 0 };
1004 
1005 // SDI RX Status Registers (for setting/clearing "VPID Present" bits)
1007 
1008 
1010 {
1011  // IP 2110 Capture: Extract timecode(s) and put into inOutXferInfo.acTransferStatus.acFrameStamp.acTimeCodes...
1012  // Extract VPID and put into SDIIn VPID regs
1014  bool result (GetFrameRate(ntv2Rate, inChannel));
1015  bool isProgressive (false);
1016  const bool isMonitoring (AJADebug::IsActive(AJA_DebugUnit_Anc2110Rcv));
1018  NTV2Buffer & ancF1 (inOutXferInfo.acANCBuffer);
1019  NTV2Buffer & ancF2 (inOutXferInfo.acANCField2Buffer);
1020  AJAAncillaryData * pPkt (AJA_NULL);
1021  uint32_t vpidA(0), vpidB(0);
1022  AJAAncillaryList pkts;
1023 
1024  if (!result)
1025  return false; // Can't get frame rate
1026  if (!NTV2_IS_VALID_NTV2FrameRate(ntv2Rate))
1027  return false; // Bad frame rate
1028  if (!GetStandard(standard, inChannel))
1029  return false; // Can't get standard
1030  if (!NTV2_IS_VALID_STANDARD(standard))
1031  return false; // Bad standard
1032  isProgressive = NTV2_IS_PROGRESSIVE_STANDARD(standard);
1033  if (!ancF1.IsNULL() || !ancF2.IsNULL())
1034  if (AJA_FAILURE(AJAAncillaryList::SetFromDeviceAncBuffers(ancF1, ancF2, pkts)))
1035  return false; // Packet import failed
1036 
1037  const NTV2SmpteLineNumber smpteLineNumInfo (::GetSmpteLineNumber(standard));
1038  const uint32_t F2StartLine (isProgressive ? 0 : smpteLineNumInfo.GetLastLine()); // F2 VANC starts past last line of F1
1039 
1040  // Look for ATC and VITC...
1041  for (uint32_t ndx(0); ndx < pkts.CountAncillaryData(); ndx++)
1042  {
1043  pPkt = pkts.GetAncillaryDataAtIndex(ndx);
1044  if (pPkt->GetDID() == 0x41 && pPkt->GetSID() == 0x01) // VPID?
1045  { // VPID!
1046  if (pPkt->GetDC() != 4)
1047  continue; // Skip . . . expected DC == 4
1048  const uint32_t* pULWord (reinterpret_cast<const uint32_t*>(pPkt->GetPayloadData()));
1049  uint32_t vpidValue (pULWord ? *pULWord : 0);
1050  if (!pPkt->GetDataLocation().IsHanc())
1051  continue; // Skip . . . expected IsHANC
1052  vpidValue = NTV2EndianSwap32BtoH(vpidValue);
1054  vpidB = vpidValue;
1055  else
1056  vpidA = vpidValue;
1057  continue; // Done . . . on to next packet
1058  }
1059 
1060  const AJAAncDataType ancType (pPkt->GetAncillaryDataType());
1061  if (ancType != AJAAncDataType_Timecode_ATC)
1062  {
1063  if (ancType == AJAAncDataType_Timecode_VITC && isMonitoring)
1064  RCVWARN(GetDescription() << ": Skipped Ch" << (inChannel+1) << " VITC packet: " << pPkt->AsString(16));
1065  continue; // Not timecode . . . skip
1066  }
1067 
1068  // Got ATC packet!
1069  AJAAncillaryData_Timecode_ATC * pATCPkt(reinterpret_cast<AJAAncillaryData_Timecode_ATC*>(pPkt));
1070  if (!pATCPkt)
1071  continue;
1072 
1074  pATCPkt->GetDBB1PayloadType(payloadType);
1076  switch(payloadType)
1077  {
1079  tcNdx = ::NTV2ChannelToTimecodeIndex (inChannel, /*inEmbeddedLTC*/true, /*inIsF2*/false);
1080  break;
1082  tcNdx = ::NTV2ChannelToTimecodeIndex (inChannel, /*inEmbeddedLTC*/false, /*inIsF2*/false);
1083  break;
1085  tcNdx = ::NTV2ChannelToTimecodeIndex (inChannel, /*inEmbeddedLTC*/false, /*inIsF2*/true);
1086  break;
1087  default:
1088  break;
1089  }
1090  if (!NTV2_IS_VALID_TIMECODE_INDEX(tcNdx))
1091  continue;
1092 
1093  NTV2_RP188 ntv2rp188; // <== This is what we want to get from pATCPkt
1094  AJATimeCode ajaTC; // We can get an AJATimeCode from it via GetTimecode
1095  const AJA_FrameRate ajaRate (sNTV2Rate2AJARate[ntv2Rate]);
1096  AJATimeBase ajaTB (ajaRate);
1097 
1098  bool isDF = false;
1100  pATCPkt->GetDropFrameFlag(isDF, tcFmt);
1101 
1102  pATCPkt->GetTimecode(ajaTC, ajaTB);
1103  // There is an AJATimeCode function to get an NTV2_RP188:
1104  // ajaTC.QueryRP188(ntv2rp188.fDBB, ntv2rp188.fLo, ntv2rp188.fHi, ajaTB, isDF);
1105  // But it's not implemented! D'OH!!
1106  // Let the hacking begin...
1107 
1108  string tcStr;
1109  ajaTC.QueryString(tcStr, ajaTB, isDF);
1110  CRP188 rp188(tcStr, sNTV2Rate2TCFormat[ntv2Rate]);
1111  rp188.SetDropFrame(isDF);
1112  rp188.GetRP188Reg(ntv2rp188);
1113  // Finally, poke the RP188 timecode into the Input Timecodes array...
1114  inOutXferInfo.acTransferStatus.acFrameStamp.SetInputTimecode(tcNdx, ntv2rp188);
1115  } // for each anc packet
1116 
1117  if (isMonitoring)
1118  {
1119  NTV2TimeCodes timecodes;
1120  inOutXferInfo.acTransferStatus.GetFrameStamp().GetInputTimeCodes(timecodes, inChannel);
1121  if (!timecodes.empty()) RCVDBG("Channel" << DEC(inChannel+1) << " timecodes: " << timecodes);
1122  }
1123  if (vpidA || vpidB)
1124  {
1125  if (isMonitoring)
1126  RCVDBG(GetDescription() << ": WriteSDIInVPID Ch" << DEC(inChannel+1) << " VPIDa=" << xHEX0N(vpidA,4) << " VPIDb=" << xHEX0N(vpidB,4));
1127  WriteSDIInVPID(inChannel, vpidA, vpidB);
1128  }
1129  WriteRegister(gSDIInRxStatusRegs[inChannel], vpidA ? 1 : 0, BIT(20), 20); // Set RX VPID Valid LinkA bit if vpidA non-zero
1130  WriteRegister(gSDIInRxStatusRegs[inChannel], vpidB ? 1 : 0, BIT(21), 21); // Set RX VPID Valid LinkB bit if vpidB non-zero
1131 
1132  // Normalize to SDI/GUMP...
1133  return AJA_SUCCESS(pkts.GetTransmitData(ancF1, ancF2, isProgressive, F2StartLine));
1134 
1135 } // S2110DeviceAncFromXferBuffers
1136 
1137 
1139 {
1140  // IP 2110 Capture: Extract timecode(s) and put into RP188 registers
1141  // Extract VPID and put into SDIIn VPID registers
1142  AUTOCIRCULATE_TRANSFER tmpXfer; tmpXfer.acANCBuffer = ancF1; tmpXfer.acANCField2Buffer = ancF2;
1143  if (!S2110DeviceAncFromXferBuffers (inChannel, tmpXfer)) // <== This handles stuffing the VPID regs
1144  {RCVFAIL(GetDescription() << ": Ch" << (inChannel+1) << ": S2110DeviceAncFromXferBuffers failed"); return false;}
1145 
1146  NTV2TimeCodes timecodes;
1147  if (!tmpXfer.acTransferStatus.GetFrameStamp().GetInputTimeCodes(timecodes, inChannel))
1148  {RCVFAIL(GetDescription() << ": Ch" << (inChannel+1) << ": GetInputTimeCodes failed"); return false;}
1149 
1150  for (NTV2TimeCodesConstIter iter(timecodes.begin()); iter != timecodes.end(); ++iter)
1151  {
1152  //const bool isLTC (NTV2_IS_ATC_LTC_TIMECODE_INDEX(iter->first));
1153  const NTV2_RP188 ntv2rp188 (iter->second);
1154  SetRP188Data (inChannel, ntv2rp188); // Poke the timecode into the SDIIn timecode regs
1155  } // for each good timecode associated with "inChannel"
1156  // No need to log timecodes, already done in S2110DeviceAncFromXferBuffers: //ANCDBG(timecodes);
1157 
1158  return true;
1159 
1160 } // S2110DeviceAncFromBuffers
1161 
1162 
1163 static inline uint32_t EndianSwap32NtoH (const uint32_t inValue) {return NTV2EndianSwap32BtoH(inValue);} // Guaranteed no in-place byte-swap -- always copies
1164 
1165 
1167 {
1168  // IP 2110 Playout: Add relevant transmit timecodes and VPID to outgoing RTP Anc
1170  bool result (GetFrameRate(ntv2Rate, inChannel));
1171  bool isProgressive (false);
1172  bool generateRTP (false);
1173  const bool isMonitoring (AJADebug::IsActive(AJA_DebugUnit_Anc2110Xmit));
1174  const bool isIoIP2110 ((_boardID == DEVICE_ID_IOIP_2110) || (_boardID == DEVICE_ID_IOIP_2110_RGB12));
1176  NTV2Buffer & ancF1 (inOutXferInfo.acANCBuffer);
1177  NTV2Buffer & ancF2 (inOutXferInfo.acANCField2Buffer);
1178  NTV2TaskMode taskMode (NTV2_OEM_TASKS);
1179  ULWord vpidA(0), vpidB(0);
1180  AJAAncillaryList packetList;
1181  const NTV2Channel SDISpigotChannel(GetTaskMode(taskMode) && NTV2_IS_STANDARD_TASKS(taskMode) ? NTV2_CHANNEL3 : inChannel);
1182  ULWord F1OffsetFromBottom(0), F2OffsetFromBottom(0), F1MonOffsetFromBottom(0), F2MonOffsetFromBottom(0);
1183  if (!result)
1184  return false; // Can't get frame rate
1185  if (!NTV2_IS_VALID_NTV2FrameRate(ntv2Rate))
1186  return false; // Bad frame rate
1187  if (!GetStandard(standard, inChannel))
1188  return false; // Can't get standard
1189  if (!NTV2_IS_VALID_STANDARD(standard))
1190  return false; // Bad standard
1191  isProgressive = NTV2_IS_PROGRESSIVE_STANDARD(standard);
1192  const NTV2SmpteLineNumber smpteLineNumInfo (::GetSmpteLineNumber(standard));
1193  const uint32_t F2StartLine (smpteLineNumInfo.GetLastLine()); // F2 VANC starts past last line of F1
1194 
1195  // IoIP 2110 Playout requires RTP+GUMP per anc buffer to operate SDI5 Mon output...
1196  GetAncRegionOffsetFromBottom(F1OffsetFromBottom, NTV2_AncRgn_Field1);
1197  GetAncRegionOffsetFromBottom(F2OffsetFromBottom, NTV2_AncRgn_Field2);
1198  GetAncRegionOffsetFromBottom(F1MonOffsetFromBottom, NTV2_AncRgn_MonField1);
1199  GetAncRegionOffsetFromBottom(F2MonOffsetFromBottom, NTV2_AncRgn_MonField2);
1200  // Define F1 & F2 GUMP sub-buffers from ancF1 & ancF2 (only used for IoIP 2110)...
1201  NTV2Buffer gumpF1(ancF1.GetHostAddress(F1OffsetFromBottom - F1MonOffsetFromBottom), // addr
1202  F1MonOffsetFromBottom - F2OffsetFromBottom); // byteCount
1203  NTV2Buffer gumpF2(ancF2.GetHostAddress(F2OffsetFromBottom - F2MonOffsetFromBottom), // addr
1204  F2MonOffsetFromBottom); // byteCount
1205 
1206  if (ancF1 || ancF2)
1207  {
1208  // Import anc packet list that AutoCirculateTransfer's caller put into Xfer struct's Anc buffers (GUMP or RTP).
1209  // We're going to add VPID and timecode packets to the list.
1210  if (AJA_FAILURE(AJAAncillaryList::SetFromDeviceAncBuffers(ancF1, ancF2, packetList)))
1211  return false; // Packet import failed
1212 
1213  if (!packetList.IsEmpty())
1214  {
1215  const bool isF1RTP (ancF1 ? AJARTPAncPayloadHeader::BufferStartsWithRTPHeader(ancF1) : false);
1216  const bool isF2RTP (ancF2 ? AJARTPAncPayloadHeader::BufferStartsWithRTPHeader(ancF2) : false);
1217  if (isIoIP2110 && isF1RTP && isF2RTP)
1218  { // Generate F1 & F2 GUMP from F1 & F2 RTP...
1219  packetList.GetSDITransmitData(gumpF1, gumpF2, isProgressive, F2StartLine);
1220  }
1221  else
1222  {
1223  if (ancF1)
1224  {
1225  if (isF1RTP)
1226  { // Caller F1 buffer contains RTP
1227  if (isIoIP2110)
1228  { // Generate GUMP from packetList...
1229  NTV2Buffer skipF2Data;
1230  packetList.GetSDITransmitData(gumpF1, skipF2Data, isProgressive, F2StartLine);
1231  }
1232  }
1233  else
1234  { // Caller F1 buffer contains GUMP
1235  generateRTP = true; // Force conversion to RTP
1236  if (isIoIP2110)
1237  { // Copy GUMP to where the driver expects it...
1238  const ULWord gumpLength (std::min(F1MonOffsetFromBottom - F2OffsetFromBottom, gumpF1.GetByteCount()));
1239  gumpF1.CopyFrom(/*src=*/ancF1, /*srcOffset=*/0, /*dstOffset=*/0, /*byteCount=*/gumpLength);
1240  } // if IoIP
1241  } // if F1 is GUMP
1242  } // if ancF1 non-NULL
1243  if (ancF2)
1244  {
1245  if (isF2RTP)
1246  { // Caller F2 buffer contains RTP
1247  if (isIoIP2110)
1248  { // Generate GUMP from packetList...
1249  NTV2Buffer skipF1Data;
1250  packetList.GetSDITransmitData(skipF1Data, gumpF2, isProgressive, F2StartLine);
1251  }
1252  }
1253  else
1254  { // Caller F2 buffer contains GUMP
1255  generateRTP = true; // Force conversion to RTP
1256  if (isIoIP2110)
1257  { // Copy GUMP to where the driver expects it...
1258  const ULWord gumpLength (std::min(F2MonOffsetFromBottom, gumpF2.GetByteCount()));
1259  gumpF2.CopyFrom(/*src=*/ancF2, /*srcOffset=*/0, /*dstOffset=*/0, /*byteCount=*/gumpLength);
1260  } // if IoIP
1261  } // if F2 is GUMP
1262  } // if ancF2 non-NULL
1263  } // else not IoIP or not F1RTP or not F2RTP
1264  } // if caller supplied any anc
1265  } // if either buffer non-empty/NULL
1266 
1267  if (isMonitoring) XMTDBG("ORIG: " << packetList); // Original packet list from caller
1268 
1269  // Callers can override our register-based VPID values...
1270  if (!packetList.CountAncillaryDataWithID(0x41,0x01)) // If no VPID packets in buffer...
1271  {
1272  if (GetSDIOutVPID(vpidA, vpidB, UWord(SDISpigotChannel))) // ...then we'll add them...
1273  {
1274  AJAAncillaryData vpidPkt;
1275  vpidPkt.SetDID(0x41);
1276  vpidPkt.SetSID(0x01);
1281  if (vpidA)
1282  { // LinkA/DS1:
1283  vpidA = ::EndianSwap32NtoH(vpidA);
1284  vpidPkt.SetPayloadData (reinterpret_cast<uint8_t*>(&vpidA), 4);
1285  vpidPkt.SetLocationLineNumber(sVPIDLineNumsF1[standard]);
1286  vpidPkt.GeneratePayloadData();
1287  packetList.AddAncillaryData(vpidPkt); generateRTP = true;
1288  if (!isProgressive)
1289  { // Ditto for Field 2...
1290  vpidPkt.SetLocationLineNumber(sVPIDLineNumsF2[standard]);
1291  packetList.AddAncillaryData(vpidPkt); generateRTP = true;
1292  }
1293  }
1294  if (vpidB)
1295  { // LinkB/DS2:
1296  vpidB = ::EndianSwap32NtoH(vpidB);
1297  vpidPkt.SetPayloadData (reinterpret_cast<uint8_t*>(&vpidB), 4);
1300  vpidPkt.GeneratePayloadData();
1301  packetList.AddAncillaryData(vpidPkt); generateRTP = true;
1302  if (!isProgressive)
1303  { // Ditto for Field 2...
1304  vpidPkt.SetLocationLineNumber(sVPIDLineNumsF2[standard]);
1305  packetList.AddAncillaryData(vpidPkt); generateRTP = true;
1306  }
1307  }
1308  } // if user not inserting his own VPID
1309  else if (isMonitoring) {XMTWARN("GetSDIOutVPID failed for SDI spigot " << ::NTV2ChannelToString(SDISpigotChannel,true));}
1310  } // if no VPID pkts in buffer
1311  else if (isMonitoring) {XMTDBG(DEC(packetList.CountAncillaryDataWithID(0x41,0x01)) << " VPID packet(s) already provided, won't insert any here");}
1312  // IoIP monitor GUMP VPID cannot be overridden -- SDI anc insert always inserts VPID via firmware
1313 
1314  // Callers can override our register-based RP188 values...
1315  if (!packetList.CountAncillaryDataWithType(AJAAncDataType_Timecode_ATC) // if no caller-specified ATC timecodes...
1316  && !packetList.CountAncillaryDataWithType(AJAAncDataType_Timecode_VITC)) // ...and no caller-specified VITC timecodes...
1317  {
1318  if (inOutXferInfo.acOutputTimeCodes) // ...and if there's an output timecode array...
1319  {
1320  const AJA_FrameRate ajaRate (sNTV2Rate2AJARate[ntv2Rate]);
1321  const AJATimeBase ajaTB (ajaRate);
1322  const NTV2TCIndexes tcIndexes (::GetTCIndexesForSDIConnector(SDISpigotChannel));
1323  const size_t maxNumTCs (inOutXferInfo.acOutputTimeCodes.GetByteCount() / sizeof(NTV2_RP188));
1324  NTV2_RP188 * pTimecodes (reinterpret_cast<NTV2_RP188*>(inOutXferInfo.acOutputTimeCodes.GetHostPointer()));
1325 
1326  // For each timecode index for this channel...
1327  for (NTV2TCIndexesConstIter it(tcIndexes.begin()); it != tcIndexes.end(); ++it)
1328  {
1329  const NTV2TCIndex tcNdx(*it);
1330  if (size_t(tcNdx) >= maxNumTCs)
1331  continue; // Skip -- not in the array
1332  if (!NTV2_IS_SDI_TIMECODE_INDEX(tcNdx))
1333  continue; // Skip -- analog or invalid
1334 
1335  const NTV2_RP188 regTC (pTimecodes[tcNdx]);
1336  if (!regTC)
1337  continue; // Skip -- invalid timecode (all FFs)
1338 
1339  const bool isDF = AJATimeCode::QueryIsRP188DropFrame(regTC.fDBB, regTC.fLo, regTC.fHi);
1340 
1341  AJATimeCode tc; tc.SetRP188(regTC.fDBB, regTC.fLo, regTC.fHi, ajaTB);
1342  AJAAncillaryData_Timecode_ATC atc; atc.SetTimecode (tc, ajaTB, isDF);
1343  atc.SetDBB (uint8_t(regTC.fDBB & 0x000000FF), uint8_t(regTC.fDBB & 0x0000FF00 >> 8));
1344  if (NTV2_IS_ATC_VITC2_TIMECODE_INDEX(tcNdx)) // VITC2?
1345  {
1347  atc.SetLocationLineNumber(sVPIDLineNumsF2[standard] - 1); // Line 9 in F2
1348  }
1349  else
1350  { // F1 -- only consider LTC and VITC1 ... nothing else
1351  if (NTV2_IS_ATC_VITC1_TIMECODE_INDEX(tcNdx)) // VITC1?
1353  else if (NTV2_IS_ATC_LTC_TIMECODE_INDEX(tcNdx)) // LTC?
1355  else
1356  continue;
1357  }
1358  atc.GeneratePayloadData();
1359  packetList.AddAncillaryData(atc); generateRTP = true;
1360  } // for each timecode index value
1361  } // if user not inserting his own ATC/VITC
1362  else if (isMonitoring) {XMTWARN("Cannot insert ATC/VITC -- Xfer struct has no acOutputTimeCodes array!");}
1363  } // if no ATC/VITC packets in buffer
1364  else if (isMonitoring) {XMTDBG("ATC and/or VITC packet(s) already provided, won't insert any here");}
1365  // IoIP monitor GUMP VPID cannot be overridden -- SDI anc inserter inserts RP188 via firmware
1366 
1367  if (generateRTP) // if anything added (or forced conversion from GUMP)
1368  { // Re-encode packets into the XferStruct buffers as RTP...
1369  //XMTDBG("CHGD: " << packetList); // DEBUG: Changed packet list (to be converted to RTP)
1370  const bool multiRTPPkt = inOutXferInfo.acTransferStatus.acState == NTV2_AUTOCIRCULATE_INVALID ? true : false;
1371  packetList.SetAllowMultiRTPTransmit(multiRTPPkt);
1372  NTV2Buffer rtpF1 (ancF1.GetHostAddress(0), isIoIP2110 ? F1OffsetFromBottom - F1MonOffsetFromBottom : ancF1.GetByteCount());
1373  NTV2Buffer rtpF2 (ancF2.GetHostAddress(0), isIoIP2110 ? F2OffsetFromBottom - F2MonOffsetFromBottom : ancF2.GetByteCount());
1374  result = AJA_SUCCESS(packetList.GetIPTransmitData (rtpF1, rtpF2, isProgressive, F2StartLine));
1375  //if (isIoIP2110) XMTDBG("F1RTP: " << rtpF1 << " F2RTP: " << rtpF2 << " Xfer: " << inOutXferInfo);
1376 #if 0
1377  DMAWriteAnc(31, rtpF1, rtpF2, NTV2_CHANNEL_INVALID); // DEBUG: DMA RTP into frame 31
1378  if (result)
1379  {
1380  AJAAncillaryList compareRTP; // RTP into compareRTP
1382  //if (packetList.GetAncillaryDataWithID(0x61,0x02)->GetChecksum() != compareRTP.GetAncillaryDataWithID(0x61,0x02)->GetChecksum())
1383  //XMTDBG("COMPRTP608: " << packetList.GetAncillaryDataWithID(0x61,0x02)->AsString(8) << compareRTP.GetAncillaryDataWithID(0x61,0x02)->AsString(8));
1384  string compRTP (compareRTP.CompareWithInfo(packetList, /*ignoreLocation*/false, /*ignoreChecksum*/false));
1385  if (!compRTP.empty())
1386  XMTWARN("MISCOMPARE: " << compRTP);
1387  }
1388  if (isIoIP2110)
1389  {
1390  DMAWriteAnc(32, gumpF1, gumpF2, NTV2_CHANNEL_INVALID); // DEBUG: DMA GUMP into frame 32
1391  if (result)
1392  {
1393  AJAAncillaryList compareGUMP; // GUMP into compareGUMP
1394  NTV2_ASSERT(AJA_SUCCESS(AJAAncillaryList::SetFromDeviceAncBuffers(gumpF1, gumpF2, compareGUMP)));
1395  //if (packetList.GetAncillaryDataWithID(0x61,0x02)->GetChecksum() != compareGUMP.GetAncillaryDataWithID(0x61,0x02)->GetChecksum())
1396  //XMTDBG("COMPGUMP608: " << packetList.GetAncillaryDataWithID(0x61,0x02)->AsString(8) << compareGUMP.GetAncillaryDataWithID(0x61,0x02)->AsString(8));
1397  string compGUMP (compareGUMP.CompareWithInfo(packetList, /*ignoreLocation*/false, /*ignoreChecksum*/false));
1398  if (!compGUMP.empty())
1399  XMTWARN("MISCOMPARE: " << compGUMP);
1400  }
1401  } // IoIP2110
1402 #endif
1403  } // if generateRTP
1404  return result;
1405 
1406 } // S2110DeviceAncToXferBuffers
1407 
1408 
1410 {
1411  // IP 2110 Playout: Add relevant transmit timecodes and VPID to outgoing RTP Anc
1413  bool result (GetFrameRate(ntv2Rate, inChannel));
1414  bool isProgressive (false);
1415  bool changed (false);
1416  const bool isMonitoring (AJADebug::IsActive(AJA_DebugUnit_Anc2110Xmit));
1418  const NTV2Channel SDISpigotChannel(inChannel); // DMAWriteAnc usually for OEM clients -- just use inChannel
1419  ULWord vpidA(0), vpidB(0);
1420  AJAAncillaryList pkts;
1421 
1422  if (!result)
1423  return false; // Can't get frame rate
1424  if (!NTV2_IS_VALID_NTV2FrameRate(ntv2Rate))
1425  return false; // Bad frame rate
1426  if (!GetStandard(standard, inChannel))
1427  return false; // Can't get standard
1428  if (!NTV2_IS_VALID_STANDARD(standard))
1429  return false; // Bad standard
1430  isProgressive = NTV2_IS_PROGRESSIVE_STANDARD(standard);
1431  if (!ancF1.IsNULL() || !ancF2.IsNULL())
1432  if (AJA_FAILURE(AJAAncillaryList::SetFromDeviceAncBuffers(ancF1, ancF2, pkts)))
1433  return false; // Packet import failed
1434 
1435  const NTV2SmpteLineNumber smpteLineNumInfo (::GetSmpteLineNumber(standard));
1436  const uint32_t F2StartLine (smpteLineNumInfo.GetLastLine()); // F2 VANC starts past last line of F1
1437 
1438  // Non-autocirculate users can transmit VPID two ways:
1439  // 1) Insert a VPID packet into the Anc buffer(s) themselves, or
1440  // 2) Set the SDI Out VPID register before calling DMAWriteAnc
1441  // Extract VPID and place into our SDI In VPID register...
1442  if (pkts.CountAncillaryDataWithID(0x41,0x01)) // If no VPID packets in buffer...
1443  {
1444  if (GetSDIOutVPID(vpidA, vpidB, UWord(SDISpigotChannel))) // ...then we'll add them...
1445  {
1446  AJAAncillaryData vpidPkt;
1447  vpidPkt.SetDID(0x41);
1448  vpidPkt.SetSID(0x01);
1453  if (vpidA)
1454  { // LinkA/DS1:
1455  vpidA = ::EndianSwap32NtoH(vpidA);
1456  vpidPkt.SetPayloadData (reinterpret_cast<uint8_t*>(&vpidA), 4);
1457  vpidPkt.SetLocationLineNumber(sVPIDLineNumsF1[standard]);
1458  pkts.AddAncillaryData(vpidPkt); changed = true;
1459  if (!isProgressive)
1460  { // Ditto for Field 2...
1461  vpidPkt.SetLocationLineNumber(sVPIDLineNumsF2[standard]);
1462  pkts.AddAncillaryData(vpidPkt); changed = true;
1463  }
1464  }
1465  if (vpidB)
1466  { // LinkB/DS2:
1467  vpidB = ::EndianSwap32NtoH(vpidB);
1468  vpidPkt.SetPayloadData (reinterpret_cast<uint8_t*>(&vpidB), 4);
1471  vpidPkt.GeneratePayloadData();
1472  pkts.AddAncillaryData(vpidPkt); changed = true;
1473  if (!isProgressive)
1474  { // Ditto for Field 2...
1475  vpidPkt.SetLocationLineNumber(sVPIDLineNumsF2[standard]);
1476  pkts.AddAncillaryData(vpidPkt); changed = true;
1477  }
1478  }
1479  } // if client didn't insert their own VPID
1480  } // if no VPID pkts in buffer
1481  else if (isMonitoring) {XMTDBG(DEC(pkts.CountAncillaryDataWithID(0x41,0x01)) << " VPID packet(s) already provided, won't insert any here");}
1482 
1483  // Non-autocirculate users can transmit timecode two ways:
1484  // 1) Insert ATC or VITC packets into the Anc buffers themselves, or
1485  // 2) Set output timecode using RP188 registers using CNTV2Card::SetRP188Data,
1486  // (but this will only work on newer boards with bidirectional SDI)
1487  if (!pkts.CountAncillaryDataWithType(AJAAncDataType_Timecode_ATC) // if no caller-specified ATC timecodes...
1488  && !pkts.CountAncillaryDataWithType(AJAAncDataType_Timecode_VITC)) // ...and no caller-specified VITC timecodes...
1489  {
1490  if (IsSupported(kDeviceHasBiDirectionalSDI) && IsSupported(kDeviceCanDoStackedAudio)) // if newer device with bidirectional SDI
1491  {
1492  const AJA_FrameRate ajaRate (sNTV2Rate2AJARate[ntv2Rate]);
1493  const AJATimeBase ajaTB (ajaRate);
1494  const NTV2TCIndexes tcIndexes (::GetTCIndexesForSDIConnector(SDISpigotChannel));
1495  NTV2_RP188 regTC;
1496 
1497  // Supposedly, these newer devices support playout readback of their RP188 registers...
1498  GetRP188Data (inChannel, regTC);
1499  if (regTC)
1500  {
1501  // For each timecode index for this channel...
1502  for (NTV2TCIndexesConstIter it(tcIndexes.begin()); it != tcIndexes.end(); ++it)
1503  {
1504  const NTV2TCIndex tcNdx(*it);
1505  if (!NTV2_IS_SDI_TIMECODE_INDEX(tcNdx))
1506  continue; // Skip -- analog or invalid
1507 
1508  // TBD: Does the DBB indicate which timecode it's intended for?
1509  // i.e. VITC? LTC? VITC2?
1510  // For now, transmit all three... TBD
1511 
1512  const bool isDF = AJATimeCode::QueryIsRP188DropFrame(regTC.fDBB, regTC.fLo, regTC.fHi);
1513 
1514  AJATimeCode tc; tc.SetRP188(regTC.fDBB, regTC.fLo, regTC.fHi, ajaTB);
1515  AJAAncillaryData_Timecode_ATC atc; atc.SetTimecode (tc, ajaTB, isDF);
1516  atc.AJAAncillaryData_Timecode_ATC::SetDBB (uint8_t(regTC.fDBB & 0x000000FF), uint8_t(regTC.fDBB & 0x0000FF00 >> 8));
1517  if (NTV2_IS_ATC_VITC2_TIMECODE_INDEX(tcNdx)) // VITC2?
1518  {
1519  if (isProgressive)
1520  continue; // Progressive -- skip VITC2
1522  atc.SetLocationLineNumber(sVPIDLineNumsF2[standard] - 1); // Line 9 in F2
1523  }
1524  else
1525  { // F1 -- only consider LTC and VITC1 ... nothing else
1526  if (NTV2_IS_ATC_VITC1_TIMECODE_INDEX(tcNdx)) // VITC1?
1528  else if (NTV2_IS_ATC_LTC_TIMECODE_INDEX(tcNdx)) // LTC?
1530  else
1531  continue;
1532  }
1533  atc.GeneratePayloadData();
1534  pkts.AddAncillaryData(atc); changed = true;
1535  } // for each timecode index value
1536  } // if GetRP188Data returned valid timecode
1537  } // if newer device with bidirectional spigots
1538  } // if client didn't insert their own ATC/VITC
1539  else if (isMonitoring) {XMTDBG("ATC and/or VITC packet(s) already provided, won't insert any here");}
1540 
1541  if (changed)
1542  { // We must re-encode packets into the RTP buffers only if anything new was added...
1543  ancF1.Fill(ULWord(0)); ancF2.Fill(ULWord(0)); // Clear/reset anc RTP buffers
1544  //XMTDBG(pkts);
1545  result = AJA_SUCCESS(pkts.GetIPTransmitData (ancF1, ancF2, isProgressive, F2StartLine));
1546 #if 0
1547  if (result)
1548  {
1549  AJAAncillaryList comparePkts;
1551  //XMTDBG(comparePkts);
1552  string compareResult (comparePkts.CompareWithInfo(pkts,false,false));
1553  if (!compareResult.empty())
1554  XMTWARN("MISCOMPARE: " << compareResult);
1555  }
1556 #endif
1557  }
1558  return result;
1559 
1560 } // S2110DeviceAncToBuffers
NTV2_RP188 acRP188
Will be deprecated – use AUTOCIRCULATE_TRANSFER::SetOutputTimeCode instead.
Anc Field2 byte offset from end of frame buffer (GUMP on all boards except RTP for SMPTE2022/IP) ...
#define IS_LINKB_AJAAncDataStream(_x_)
virtual bool AutoCirculateFlush(const NTV2Channel inChannel, const bool inClearDropCount=(0))
Flushes AutoCirculate for the given channel.
NTV2TCIndexes GetTCIndexesForSDIConnector(const NTV2Channel inSDIConnector)
Definition: ntv2utils.cpp:4970
NTV2Buffer acOutputTimeCodes
Intended for playout, this is an ordered sequence of NTV2_RP188 values to send to the device...
virtual const uint8_t * GetPayloadData(void) const
virtual uint8_t GetDID(void) const
#define NTV2_IS_ATC_VITC1_TIMECODE_INDEX(__x__)
Definition: ntv2enums.h:3988
#define AJA_SUCCESS(_status_)
Definition: types.h:372
#define NTV2_IS_INPUT_MODE(__mode__)
Definition: ntv2enums.h:1249
ULWord frame
The frame requested or -1 if not available.
virtual AJAStatus GetTransmitData(NTV2Buffer &F1Buffer, NTV2Buffer &F2Buffer, const bool inIsProgressive=true, const uint32_t inF2StartLine=0)
Encodes my AJAAncillaryData packets into the given buffers in the default SDI Anc Buffer Data Format ...
virtual AJAStatus SetDBB(uint8_t dbb1, uint8_t dbb2)
NTV2AudioSystem
Used to identify an Audio System on an NTV2 device. See Audio System Operation for more information...
Definition: ntv2enums.h:3895
Declares the AJALock class.
bool GetBadRegions(ULWordSequence &outBlks) const
Answers with the list of colliding and illegal memory regions.
Definition: ntv2card.h:6973
std::set< NTV2TCIndex > NTV2TCIndexes
virtual uint32_t CountAncillaryData(void) const
Answers with the number of AJAAncillaryData objects I contain (any/all types).
The ancillary data is associated with DS2 of the video stream (Link A).
bool Allocate(const size_t inByteCount, const bool inPageAligned=false)
Allocates (or re-allocates) my user-space storage using the given byte count. I assume full responsib...
SMPTE 12-M Vertical Interval Timecode (aka "VITC")
Definition: ancillarydata.h:49
NTV2Crosspoint
Logically, these are an NTV2Channel combined with an NTV2Mode.
Definition: ntv2enums.h:1700
#define AUTOCIRCULATE_WITH_MULTILINK_AUDIO3
Use this to AutoCirculate with base audiosystem controlling base AudioSystem + 3. ...
virtual AJAStatus SetDBB1PayloadType(const AJAAncillaryData_Timecode_ATC_DBB1PayloadType inType)
Sets my payload type.
virtual uint8_t GetSID(void) const
SMPTE 12-M Ancillary Timecode (formerly known as "RP-188")
Definition: ancillarydata.h:48
virtual AJAStatus SetSID(const uint8_t inSID)
Sets my Secondary Data ID (SID) - (aka the Data Block Number (DBN) for "Type 1" SMPTE-291 packets)...
This identifies the invalid (unspecified, uninitialized) VANC mode.
Definition: ntv2enums.h:3802
virtual AJAStatus GeneratePayloadData(void)
Generate the payload data from the "local" ancillary data.
bool IsNULL(void) const
#define NTV2_IS_SDI_TIMECODE_INDEX(__x__)
Definition: ntv2enums.h:3997
#define DEC0N(__x__, __n__)
See Io IP.
Definition: ntv2enums.h:41
I interrogate and control an AJA video/audio capture/playout device.
Definition: ntv2card.h:28
#define BIT(_x_)
Definition: ajatypes.h:578
NTV2ChannelSet::const_iterator NTV2ChannelSetConstIter
A handy const iterator into an NTV2ChannelSet.
NTV2TaskMode
Describes the task mode state. See also: Sharing AJA Devices With Other Applications.
virtual AJAStatus SetDID(const uint8_t inDataID)
Sets my Data ID (DID).
static bool BufferStartsWithRTPHeader(const NTV2Buffer &inBuffer)
#define NTV2_IS_ATC_LTC_TIMECODE_INDEX(__x__)
Definition: ntv2enums.h:3993
Declares the AJADebug class.
bool CopyFrom(const void *pInSrcBuffer, const ULWord inByteCount)
Replaces my contents from the given memory buffer, resizing me to the new byte count.
SDI 1 embedded VITC 2.
Definition: ntv2enums.h:3972
virtual AJAAncillaryData * GetAncillaryDataAtIndex(const uint32_t inIndex) const
Answers with the AJAAncillaryData object at the given index.
enum _NTV2VideoFormat NTV2VideoFormat
Identifies a particular video format.
Audits an NTV2 device&#39;s SDRAM utilization, and can report contiguous regions of SDRAM, whether unused/free, those being read/written by AutoCirculate, those being read/written by non-AutoCirculating FrameStores, those that are in conflict (AutoCirculate, FrameStore and/or Audio collisions), plus invalid/out-of-bounds regions being accessed.
Definition: ntv2card.h:6908
Used to describe Start of Active Video (SAV) location and field dominance for a given NTV2Standard...
Definition: ntv2utils.h:879
static bool GetCurrentACChannelCrosspoint(CNTV2Card &inDevice, const NTV2Channel inChannel, NTV2Crosspoint &outCrosspoint)
virtual AJAStatus SetLocationHorizOffset(const uint16_t inOffset)
Sets my ancillary data "location" horizontal offset.
The number of independent Audio Systems on the device.
#define NTV2EndianSwap32BtoH(__val__)
Definition: ntv2endian.h:63
bool TranslateRegions(ULWordSequence &outRgns, const ULWordSequence &inRgns, const bool inIsQuad, const bool inIsQuadQuad) const
Translates an 8MB-chunked list of regions into another list of regions with frame indexes and sizes e...
Definition: ntv2card.cpp:762
#define NTV2_IS_VALID_AUDIO_RATE(_x_)
Definition: ntv2enums.h:1937
#define AJA_FAILURE(_status_)
Definition: types.h:373
Identifies the "monitor" or "auxiliary" Field 2 ancillary data region.
Definition: ntv2enums.h:4232
UWord count(void) const
Definition: ntv2utils.h:984
virtual const AJAAncDataLoc & GetDataLocation(void) const
AJAAncDataType
Identifies the ancillary data types that are known to this module.
Definition: ancillarydata.h:44
bool IsHanc(void) const
bool IsValid(void) const
Answers true if I&#39;m valid, or false if I&#39;m not valid.
ULWord GetByteCount(void) const
virtual bool GetFrameStamp(NTV2Crosspoint channelSpec, ULWord frameNum, FRAME_STAMP_STRUCT *pFrameStamp)
bool WithAudio(void) const
int32_t LWord
Definition: ajatypes.h:222
#define RCVFAIL(__x__)
AJAAncDataStream GetDataStream(void) const
#define AUTOCIRCULATE_WITH_FBFCHANGE
Use this to AutoCirculate with the possibility of frame buffer format changes.
LWord64 acFrameTime
(input/ingest/capture only) The absolute timestamp at the VBI when the frame started recording into d...
FRAME_STAMP acFrameStamp
Frame stamp for the transferred frame.
virtual std::string AsString(const uint16_t inDumpMaxBytes=0) const
Definition: lock.h:28
Defines a number of handy byte-swapping macros.
The "default" timecode (mostly used by the AJA "Retail" service and Control Panel) ...
Definition: ntv2enums.h:3953
#define NTV2_IS_STANDARD_TASKS(__m__)
static bool QueryIsRP188DropFrame(const uint32_t inDBB, const uint32_t inLo, const uint32_t inHi)
Definition: timecode.cpp:563
UWord firstFrame(void) const
Definition: ntv2utils.h:985
#define NTV2_IS_VALID_TIMECODE_INDEX(__x__)
Definition: ntv2enums.h:3984
virtual bool FindUnallocatedFrames(const UWord inFrameCount, LWord &outStartFrame, LWord &outEndFrame, const NTV2Channel inFrameStore=NTV2_CHANNEL_INVALID)
Returns the device frame buffer numbers of the first unallocated contiguous band of frame buffers hav...
Definition: json.hpp:5362
static bool IsActive(int32_t index)
Definition: debug.cpp:279
#define NTV2ChannelToOutputChannelSpec
Definition: ntv2utils.h:598
uint32_t ULWord
Definition: ajatypes.h:223
virtual bool AutoCirculateGetStatus(const NTV2Channel inChannel, AUTOCIRCULATE_STATUS &outStatus)
Returns the current AutoCirculate status for the given channel.
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They&#39;re also commonly use...
Definition: ntv2enums.h:1357
ULWord GetLastLine(const NTV2FieldID inRasterFieldID=NTV2_FIELD0) const
#define AUTOCIRCULATE_WITH_MULTILINK_AUDIO1
Use this to AutoCirculate with base audiosystem controlling base AudioSystem + 1. ...
static uint32_t EndianSwap32NtoH(const uint32_t inValue)
static const uint32_t gSDIInRxStatusRegs[]
True if device supports grouped audio system control.
NTV2Crosspoint acCrosspoint
Will be deprecated – used internally by the SDK. Will be removed when the driver changes to use NTV2...
virtual AJAStatus SetLocationLineNumber(const uint16_t inLineNum)
Sets my ancillary data "location" frame line number.
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:476
virtual AJAAncDataType GetAncillaryDataType(void) const
bool GetInputTimeCodes(NTV2TimeCodeList &outValues) const
Returns all RP188 timecodes associated with the frame in NTV2TCIndex order.
Represents an unknown or invalid frame rate.
Definition: ntv2enums.h:414
NTV2AutoCirculateState acState
Current AutoCirculate state after the transfer.
void * PVOID
Definition: ajatypes.h:286
This struct replaces the old RP188_STRUCT.
virtual AJAStatus GetSDITransmitData(NTV2Buffer &F1Buffer, NTV2Buffer &F2Buffer, const bool inIsProgressive=true, const uint32_t inF2StartLine=0)
Anc Field1 byte offset from end of frame buffer (GUMP on all boards except RTP for SMPTE2022/IP) ...
NTV2TCIndex NTV2ChannelToTimecodeIndex(const NTV2Channel inChannel, const bool inEmbeddedLTC=false, const bool inIsF2=false)
Converts the given NTV2Channel value into the equivalent NTV2TCIndex value.
Definition: ntv2utils.cpp:4962
NTV2TCIndex
These enum values are indexes into the capture/playout AutoCirculate timecode arrays.
Definition: ntv2enums.h:3951
bool Fill(const T &inValue)
Fills me with the given scalar value.
True if device SDI connectors are bi-directional.
AutoCirculate Frame Range.
Definition: ntv2utils.h:971
bool Deallocate(void)
Deallocates my user-space storage (if I own it – i.e. from a prior call to Allocate).
static AJAAncillaryData_Timecode_Format GetTimecodeFormatFromTimeBase(const AJATimeBase &inTimeBase)
Get the timecode format that matches the input timebase.
NTV2FrameRate
Identifies a particular video frame rate.
Definition: ntv2enums.h:412
#define true
Analog LTC 1.
Definition: ntv2enums.h:3960
NTV2Standard
Identifies a particular video standard.
Definition: ntv2enums.h:165
Playout (output) mode, which reads from device SDRAM.
Definition: ntv2enums.h:1241
virtual uint32_t CountAncillaryDataWithID(const uint8_t inDID, const uint8_t inSID) const
Answers with the number of AncillaryData objects having the given DataID and SecondaryID.
virtual bool IsOpen(void) const
The invalid mode.
Definition: ntv2enums.h:1245
#define NTV2_IS_ATC_VITC2_TIMECODE_INDEX(__x__)
Definition: ntv2enums.h:3991
virtual bool S2110DeviceAncFromBuffers(const NTV2Channel inChannel, NTV2Buffer &ancF1, NTV2Buffer &ancF2)
virtual bool AutoCirculateTransfer(const NTV2Channel inChannel, AUTOCIRCULATE_TRANSFER &transferInfo)
Transfers all or part of a frame as specified in the given AUTOCIRCULATE_TRANSFER object to/from the ...
Utility class for timecodes.
Definition: timecode.h:28
static const uint16_t sVPIDLineNumsF2[]
virtual AJAStatus SetLocationDataStream(const AJAAncDataStream inStream)
Sets my ancillary data "location" data stream value (DS1,DS2...).
virtual AJAStatus SetLocationVideoLink(const AJAAncDataLink inLink)
Sets my ancillary data "location" within the video stream.
#define AJA_NULL
Definition: ajatypes.h:167
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 MAX_FRAMEBUFFERS
bool GetFreeRegions(ULWordSequence &outBlks) const
Answers with the list of free memory regions.
Definition: ntv2card.h:6963
Declares the CRP188 class. See SMPTE RP188 standard for details.
#define RCVWARN(__x__)
NTV2TimeCodes::const_iterator NTV2TimeCodesConstIter
A handy const interator for iterating over NTV2TCIndex/NTV2TimeCodeList pairs.
NTV2AutoCirculateState acState
Current AutoCirculate state.
ULWord NTV2FramesizeToByteCount(const NTV2Framesize inFrameSize)
Converts the given NTV2Framesize value into an exact byte count.
Definition: ntv2utils.cpp:5287
bool IsStopped(void) const
True if device uses a "stacked" arrangement of its audio buffers.
2: OEM (recommended): device configured by client application(s) with some driver involvement...
The ancillary data is associated with the luminance (Y) channel of the video stream.
static AJAStatus SetFromDeviceAncBuffers(const NTV2Buffer &inF1AncBuffer, const NTV2Buffer &inF2AncBuffer, AJAAncillaryList &outPackets, const uint32_t inFrameNum=0)
Returns all ancillary data packets found in the given F1 and F2 ancillary data buffers.
ULWord acRequestedFrame
On entry for NTV2_TYPE_ACFRAMESTAMP message, the requested frame. Upon exit, 0xFFFFFFFF means "not ...
static const AJA_FrameRate sNTV2Rate2AJARate[]
virtual bool AutoCirculateResume(const NTV2Channel inChannel, const bool inClearDropCount=(0))
Resumes AutoCirculate for the given channel, picking up at the next frame without loss of audio synch...
std::string NTV2VANCModeToString(const NTV2VANCMode inValue, const bool inCompactDisplay=false)
Definition: ntv2utils.cpp:6505
virtual AJAStatus AddAncillaryData(const AJAAncillaryList &inPackets)
Appends a copy of the given list&#39;s packets to me.
int64_t LWord64
Definition: ajatypes.h:225
#define ACINFO(__x__)
void SetDropFrame(bool bDropFrameFlag)
Definition: ntv2rp188.cpp:734
virtual AJAStatus GeneratePayloadData(void)
Generates the payload data from the "local" ancillary data.
#define NTV2_IS_INPUT_CROSSPOINT(__x__)
Definition: ntv2enums.h:1724
#define NTV2ChannelToInputChannelSpec
Definition: ntv2utils.h:596
#define NTV2_IS_VALID_STANDARD(__s__)
Definition: ntv2enums.h:188
The AutoCirculate channel is stopped.
#define AUTOCIRCULATE_WITH_ANC
Use this to AutoCirculate with ancillary data.
uint64_t ULWord64
Definition: ajatypes.h:226
static const char gFBAllocLockName[]
uint8_t UByte
Definition: ajatypes.h:218
virtual std::string CompareWithInfo(const AJAAncillaryList &inCompareList, const bool inIgnoreLocation=true, const bool inIgnoreChecksum=true) const
Compares me with another list and returns a std::string that contains a human-readable explanation of...
NTV2Crosspoint channelSpec
#define ACFAIL(__x__)
#define ACWARN(__x__)
#define NTV2_IS_VANCMODE_ON(__v__)
Definition: ntv2enums.h:3808
#define XMTWARN(__x__)
void Clear(void)
Clears my data.
NTV2Framesize
Kona2/Xena2 specific enums.
Definition: ntv2enums.h:2116
virtual bool S2110DeviceAncToXferBuffers(const NTV2Channel inChannel, AUTOCIRCULATE_TRANSFER &inOutXferInfo)
virtual bool AutoCirculateStop(const NTV2Channel inChannel, const bool inAbort=(0))
Stops AutoCirculate for the given channel, and releases the on-device frame buffers that were allocat...
#define NTV2_IS_VALID_CHANNEL(__x__)
Definition: ntv2enums.h:1371
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.).
std::map< NTV2TCIndex, NTV2_RP188 > NTV2TimeCodes
A mapping of NTV2TCIndex enum values to NTV2_RP188 structures.
NTV2Mode
Used to identify the mode of a widget_framestore, or the direction of an AutoCirculate stream: either...
Definition: ntv2enums.h:1239
uint16_t GetEndFrame(void) const
#define AUTOCIRCULATE_WITH_FBOCHANGE
Use this to AutoCirculate with the possibility of frame buffer orientation changes.
#define AUTOCIRCULATE_WITH_AUDIO_CONTROL
Use this to AutoCirculate with no audio but with audio control.
This object specifies the information that will be transferred to or from the AJA device in the CNTV2...
virtual bool AutoCirculateGetFrameStamp(const NTV2Channel inChannel, const ULWord inFrameNumber, FRAME_STAMP &outFrameInfo)
Returns precise timing information for the given frame and channel that&#39;s currently AutoCirculating...
virtual uint32_t CountAncillaryDataWithType(const AJAAncDataType inMatchType) const
Answers with the number of AJAAncillaryData objects having the given type.
static const uint16_t sVPIDLineNumsF1[]
Declares the AJATimeCode class.
const FRAME_STAMP & GetFrameStamp(void) const
#define DEC(__x__)
LWord GetTransferFrameNumber(void) const
NTV2Buffer acANCField2Buffer
The host "Field 2" ancillary data buffer. This field is owned by the client application, and thus is responsible for allocating and/or freeing it. If the pointer is NULL or the size is zero, no "Field 2" ancillary data will be transferred. Use the AUTOCIRCULATE_TRANSFER::SetAncBuffers method to set or reset this field.
std::set< NTV2Channel > NTV2ChannelSet
A set of distinct NTV2Channel values.
SDI 2 embedded VITC 2.
Definition: ntv2enums.h:3973
Declares the AJAAncillaryData_Timecode_ATC class.
NTV2SmpteLineNumber GetSmpteLineNumber(const NTV2Standard inStandard)
For the given video standard, returns the SMPTE-designated line numbers for Field 1 and Field 2 that ...
Definition: ntv2utils.h:965
#define NTV2_IS_QUAD_FRAME_FORMAT(__f__)
Definition: ntv2enums.h:812
Declares numerous NTV2 utility functions.
double GetAudioSamplesPerSecond(const NTV2AudioRate inAudioRate)
Returns the audio sample rate as a number of audio samples per second.
Definition: ntv2utils.cpp:3303
#define AJAAncDataHorizOffset_AnyHanc
HANC – Packet placed/found in any legal area of raster line after EAV.
The ancillary data is associated with Link A of the video stream.
Definition: ancillarydata.h:81
Identifies the "normal" Field 2 ancillary data region.
Definition: ntv2enums.h:4230
virtual AJAStatus SetTimecode(const AJATimeCode &inTimecode, const AJATimeBase &inTimeBase, const bool inIsDropFrame)
Sets my timecode "time" from an AJATimeCode.
True if device supports SMPTE ST2110.
NTV2Crosspoint NTV2ChannelToInputCrosspoint(const NTV2Channel inChannel)
Definition: ntv2utils.cpp:4915
static AJALock gFBAllocLock(gFBAllocLockName)
#define NTV2_IS_QUAD_QUAD_FORMAT(__f__)
Definition: ntv2enums.h:819
bool SetInputTimecode(const NTV2TCIndex inTCNdx, const NTV2_RP188 &inTimecode)
Sets one of my input timecodes.
#define RCVDBG(__x__)
ULWord GetFrameCount(void) const
NTV2Crosspoint NTV2ChannelToOutputCrosspoint(const NTV2Channel inChannel)
Definition: ntv2utils.cpp:4926
This is returned from the CNTV2Card::AutoCirculateGetStatus function.
#define AUTOCIRCULATE_WITH_COLORCORRECT
Use this to AutoCirculate with color correction.
#define NTV2_IS_OUTPUT_CROSSPOINT(__x__)
Definition: ntv2enums.h:1733
uint16_t UWord
Definition: ajatypes.h:221
void QueryString(std::string &str, const AJATimeBase &timeBase, bool bDropFrame, bool bStdTcForHfr, AJATimecodeNotation notation=AJA_TIMECODE_LEGACY)
Definition: timecode.cpp:299
#define ACDBG(__x__)
1: Standard/Retail: device configured by AJA ControlPanel, service/daemon, and driver.
virtual AJAStatus SetPayloadData(const uint8_t *pInData, const uint32_t inByteCount)
Copy data from external memory into my local payload memory.
virtual bool AutoCirculateStart(const NTV2Channel inChannel, const ULWord64 inStartTime=0)
Starts AutoCirculating the specified channel that was previously initialized by CNTV2Card::AutoCircul...
virtual AJAStatus GetIPTransmitData(NTV2Buffer &F1Buffer, NTV2Buffer &F2Buffer, const bool inIsProgressive=true, const uint32_t inF2StartLine=0)
Explicitly encodes my AJAAncillaryData packets into the given buffers in RTP Anc Buffer Data Format ...
NTV2Buffer acTimeCodes
Intended for capture, this is a sequence of NTV2_RP188 values received from the device (in NTV2TCInde...
virtual bool IsEmpty(void) const
AUTOCIRCULATE_TRANSFER_STATUS acTransferStatus
Contains status information that&#39;s valid after CNTV2Card::AutoCirculateTransfer returns, including the driver buffer level, number of frames processed or dropped, audio and anc transfer byte counts, and a complete FRAME_STAMP that has even more detailed clocking information.
enum _AutoCircCommand_ AUTO_CIRC_COMMAND
virtual bool AutoCirculateInitForOutput(const NTV2Channel inChannel, const UWord inFrameCount=7, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_INVALID, const ULWord inOptionFlags=0, const UByte inNumChannels=1, const UWord inStartFrameNumber=0, const UWord inEndFrameNumber=0)
Prepares for subsequent AutoCirculate playout, designating a contiguous block of frame buffers on the...
#define xHEX0N(__x__, __n__)
NTV2VANCMode
These enum values identify the available VANC modes.
Definition: ntv2enums.h:3797
TimecodeFormat
Definition: ntv2rp188.h:22
#define NTV2_IS_SUPPORTED_NTV2FrameRate(__r__)
Definition: ntv2enums.h:445
virtual bool S2110DeviceAncFromXferBuffers(const NTV2Channel inChannel, AUTOCIRCULATE_TRANSFER &inOutXferInfo)
#define NTV2_IS_VALID_AUDIO_SYSTEM(__x__)
Definition: ntv2enums.h:3914
virtual AJAStatus SetLocationDataChannel(const AJAAncDataChannel inChannel)
Sets my ancillary data "location" data channel value (Y or C).
bool GetTagsForFrameIndex(const UWord inIndex, NTV2StringSet &outTags) const
Answers with the list of tags for the given frame number.
Definition: ntv2card.cpp:744
bool GetInputTimeCode(NTV2_RP188 &outTimeCode, const NTV2TCIndex inTCIndex=NTV2_TCINDEX_SDI1) const
Intended for capture, answers with a specific timecode captured in my acTransferStatus member&#39;s acFra...
virtual AJAStatus GetDBB1PayloadType(AJAAncillaryData_Timecode_ATC_DBB1PayloadType &outType) const
Answers with my current payload type.
Declares the CNTV2Card class.
Identifies the "monitor" or "auxiliary" Field 1 ancillary data region.
Definition: ntv2enums.h:4231
virtual bool S2110DeviceAncToBuffers(const NTV2Channel inChannel, NTV2Buffer &ancF1, NTV2Buffer &ancF2)
virtual bool AutoCirculatePause(const NTV2Channel inChannel, const UWord inAtFrameNum=0xFFFF)
Pauses AutoCirculate for the given channel. Once paused, AutoCirculate can be resumed later by callin...
#define NTV2_IS_OUTPUT_MODE(__mode__)
Definition: ntv2enums.h:1250
I am the ATC-specific (analog) subclass of the AJAAncillaryData_Timecode class.
RP188SourceFilterSelect
Private include file for all ajabase sources.
This class/object reports information about the current and/or requested AutoCirculate frame...
bool GetRP188Reg(RP188_STRUCT &outRP188) const
Definition: ntv2rp188.cpp:1241
NTV2AudioRate
Definition: ntv2enums.h:1928
std::vector< uint32_t > ULWordSequence
An ordered sequence of ULWord (uint32_t) values.
virtual AJAStatus GetTimecode(AJATimeCode &outTimecode, const AJATimeBase &inTimeBase) const
Answers with my timecode "time" as an AJATimeCode.
SDI 2 embedded ATC LTC.
Definition: ntv2enums.h:3959
std::string join(const std::vector< std::string > &parts, const std::string &delim)
Definition: common.cpp:468
#define AUTOCIRCULATE_WITH_VIDPROC
Use this to AutoCirculate with video processing.
SDI 1 embedded ATC LTC.
Definition: ntv2enums.h:3958
virtual uint32_t GetDC(void) const
ULWord fLo
| BG 4 | Secs10 | BG 3 | Secs 1 | BG 2 | Frms10 | BG 1 | Frms 1 |
void * GetHostPointer(void) const
#define AUTOCIRCULATE_WITH_MULTILINK_AUDIO2
Use this to AutoCirculate with base audiosystem controlling base AudioSystem + 2. ...
Identifies the first field in time for an interlaced video frame, or the first and only field in a pr...
Definition: ntv2enums.h:1842
SDI 2 embedded VITC.
Definition: ntv2enums.h:3955
#define XMTDBG(__x__)
std::ostream & DumpBlocks(std::ostream &oss) const
Dumps all 8MB blocks/frames and their tags, if any, into the given stream.
Definition: ntv2card.cpp:655
NTV2TCIndexes::const_iterator NTV2TCIndexesConstIter
ULWord GetCapturedAncByteCount(const bool inField2=false) const
UWord lastFrame(void) const
Definition: ntv2utils.h:986
#define HEX0N(__x__, __n__)
Definition: debug.cpp:1175
I am the principal class that stores a single SMPTE-291 SDI ancillary data packet OR the digitized co...
#define NTV2_IS_VALID_NTV2CROSSPOINT(__x__)
Definition: ntv2enums.h:1742
virtual bool AutoCirculateInitForInput(const NTV2Channel inChannel, const UWord inFrameCount=7, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_INVALID, const ULWord inOptionFlags=0, const UByte inNumChannels=1, const UWord inStartFrameNumber=0, const UWord inEndFrameNumber=0)
Prepares for subsequent AutoCirculate ingest, designating a contiguous block of frame buffers on the ...
#define AUTOCIRCULATE_WITH_RP188
Use this to AutoCirculate with RP188.
std::string NTV2ChannelToString(const NTV2Channel inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:5727
Declares the AJAAncillaryList class.
void * GetHostAddress(const ULWord inByteOffset, const bool inFromEnd=false) const
Identifies the "normal" Field 1 ancillary data region.
Definition: ntv2enums.h:4229
NTV2AudioSystem GetAudioSystem(void) const
virtual AJAStatus GetDropFrameFlag(bool &bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown) const
NTV2Buffer acANCBuffer
The host ancillary data buffer. This field is owned by the client application, and thus is responsibl...
virtual bool GetAutoCirculate(NTV2Crosspoint channelSpec, AUTOCIRCULATE_STATUS_STRUCT *autoCirculateStatus)
AJAAncillaryData_Timecode_Format
NTV2Crosspoint channelSpec
#define AUTOCIRCULATE_WITH_FIELDS
Use this to AutoCirculate with fields as frames for interlaced formats.
bool SetAllOutputTimeCodes(const NTV2_RP188 &inTimecode, const bool inIncludeF2=true)
Intended for playout, replaces all elements of my acOutputTimeCodes member with the given timecode va...
#define AUTOCIRCULATE_WITH_HDMIAUX
Use this to AutoCirculate with HDMI auxiliary data.
AJAAncillaryData_Timecode_ATC_DBB1PayloadType
#define NTV2_IS_PROGRESSIVE_STANDARD(__s__)
Definition: ntv2enums.h:189
virtual void SetAllowMultiRTPTransmit(const bool inAllow)
Determines if multiple RTP packets will be encoded for playout (via GetIPTransmitData). The default behavior is to transmit/encode a single RTP packet.
NTV2Crosspoint acCrosspoint
The crosspoint (channel number with direction)
AJA_FrameRate
Definition: videotypes.h:210
ULWord fHi
| BG 8 | Hrs 10 | BG 7 | Hrs 1 | BG 6 | Mins10 | BG 5 | Mins 1 |
The ancillary data is associated with Link B of the video stream.
Definition: ancillarydata.h:82
uint16_t GetStartFrame(void) const
SDI 1 embedded VITC.
Definition: ntv2enums.h:3954
I am an ordered collection of AJAAncillaryData instances which represent one or more SMPTE 291 data p...
Definition: ancillarylist.h:64
#define NTV2_IS_VALID_NTV2FrameRate(__r__)
Definition: ntv2enums.h:444
The ancillary data is associated with DS1 of the video stream (Link A).
#define AUTOCIRCULATE_WITH_LTC
Use this to AutoCirculate with analog LTC.
virtual bool AutoCirculatePreRoll(const NTV2Channel inChannel, const ULWord inPreRollFrames)
Tells AutoCirculate how many frames to skip before playout starts for the given channel.
Specifies channel or FrameStore 3 (or the 3rd item).
Definition: ntv2enums.h:1361
virtual bool GetMode(const NTV2Channel inChannel, NTV2Mode &outValue)
Answers with the current NTV2Mode of the given FrameStore on the AJA device.
std::set< std::string > NTV2StringSet
Definition: ntv2utils.h:1158
virtual bool AutoCirculateSetActiveFrame(const NTV2Channel inChannel, const ULWord inNewActiveFrame)
Immediately changes the Active Frame for the given channel.
static const TimecodeFormat sNTV2Rate2TCFormat[]
ULWord GetScaleFromFrameRate(const NTV2FrameRate inFrameRate)
Definition: ntv2utils.cpp:3454
void SetRP188(const uint32_t inDBB, const uint32_t inLo, const uint32_t inHi, const AJATimeBase &inTimeBase)
Definition: timecode.cpp:570
virtual bool IsValid(void) const
Definition: lock.h:65