AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
ntv2framegrabber.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
7 #include <ostream>
8 #include "ntv2framegrabber.h"
9 #include "ntv2democommon.h"
10 #include "ntv2utils.h"
11 #if defined (INCLUDE_AJACC)
14  using namespace std;
15 #endif
16 
17 #define NTV2_NUM_IMAGES (10)
18 
19 // Convenience macros for EZ logging:
20 #define FGFAIL(_expr_) AJA_sERROR (AJA_DebugUnit_DemoCapture, AJAFUNC << ": " << _expr_)
21 #define FGWARN(_expr_) AJA_sWARNING(AJA_DebugUnit_DemoCapture, AJAFUNC << ": " << _expr_)
22 #define FGDBG(_expr_) AJA_sDEBUG (AJA_DebugUnit_DemoCapture, AJAFUNC << ": " << _expr_)
23 #define FGNOTE(_expr_) AJA_sNOTICE (AJA_DebugUnit_DemoCapture, AJAFUNC << ": " << _expr_)
24 #define FGINFO(_expr_) AJA_sINFO (AJA_DebugUnit_DemoCapture, AJAFUNC << ": " << _expr_)
25 
26 static QMutex gMutex;
27 
28 
30  : QThread (parent),
31  mRestart (true),
32  mAbort (false),
33  mCheckFor4K (false),
34  mDeinterlace (true),
35  mbFixedReference (false),
36  mBoardNumber (0),
37  mDeviceID (DEVICE_ID_NOTFOUND),
38  mChannel (NTV2_MAX_NUM_CHANNELS),
39  mNumChannels (0),
40  mTsi (false),
41  mCurrentVideoFormat (NTV2_FORMAT_UNKNOWN),
42  mCurrentColorSpace (NTV2_LHIHDMIColorSpaceYCbCr),
43  mLastVideoFormat (NTV2_FORMAT_UNKNOWN),
44  mDebounceCounter (0),
45  mFormatIsProgressive (true),
46  mInputSource (NTV2_NUM_INPUTSOURCES),
47  mFrameBufferFormat (NTV2_FBF_ARGB),
48  mDoMultiChannel (false),
49  mbWithAudio (false),
50  mAudioOutput (AJA_NULL),
51  mAudioDevice (AJA_NULL),
52  mNumAudioChannels (0),
53  mAudioSystem (NTV2_AUDIOSYSTEM_1),
54  mTimeCodeSource (NTV2_TCINDEX_INVALID)
55 {
57 } // constructor
58 
59 
61 {
62  mAbort = true;
63  while (isRunning())
64  ; // Wait for grabber thread to finish
65 
67 
68  if (mAudioOutput)
69  delete mAudioOutput;
70 
71 } // destructor
72 
73 
75 {
76  if (inInputSource != mInputSource)
77  {
78  FGDBG("From " << ::NTV2InputSourceToString (mInputSource) << " to " << ::NTV2InputSourceToString (inInputSource));
79  gMutex.lock();
80  mInputSource = inInputSource;
81  mRestart = true;
82  gMutex.unlock();
83  }
84 
85 } // SetInputSource
86 
87 
88 void NTV2FrameGrabber::SetDeviceIndex (const UWord inDeviceIndex)
89 {
90  if (inDeviceIndex != mBoardNumber)
91  {
92  gMutex.lock();
93  mBoardNumber = inDeviceIndex;
94  mRestart = true;
95  gMutex.unlock();
96  }
97 } // SetDeviceIndex
98 
99 
101 {
102  if (inTCIndex != mTimeCodeSource)
103  {
104  gMutex.lock();
105  mTimeCodeSource = inTCIndex;
106  mRestart = true;
107  gMutex.unlock();
108  }
109 } // SetTimeCodeSource
110 
111 
113 {
114  gMutex.lock();
115  const UWord result (mBoardNumber);
116  gMutex.unlock();
117  return result;
118 }
119 
120 
121 #if defined (INCLUDE_AJACC)
122  #if 0
123  static const UWord gTest [15][32] =
124  // 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
125  // 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
126  /*01*/ {{0x250C, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014,
127  0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2510},
128  /*02*/ {0x007C, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E,
129  0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x007C},
130  /*03*/ {0x007C, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005D,
131  0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x007C},
132  /*04*/ {0x007C, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0020, 0x00E1, 0x00E9, 0x00ED,
133  0x00F3, 0x00FA, 0x00E7, 0x00F7, 0x00D1, 0x00E1, 0x00F1, 0x2588, 0x00AE, 0x00B0, 0x00BD, 0x00BF, 0x2122, 0x00A2, 0x00A3, 0x007C},
134  /*05*/ {0x007C, 0x266A, 0x00E0, 0x00A0, 0x00E8, 0x00E2, 0x00EA, 0x00EE, 0x00F4, 0x00FB, 0x00C1, 0x00C9, 0x00D3, 0x00DA, 0x00DC, 0x00FC,
135  0x2018, 0x00A1, 0x002A, 0x2019, 0x2014, 0x00A9, 0x2120, 0x2022, 0x201C, 0x201D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x007C},
136  /*06*/ {0x007C, 0x00C0, 0x00C2, 0x00C7, 0x00C8, 0x00CA, 0x00CB, 0x00EB, 0x00CE, 0x00CF, 0x00EF, 0x00D4, 0x00D9, 0x00F9, 0x00DB, 0x00AB,
137  0x00BB, 0x0020, 0x0020, 0x00C3, 0x00E3, 0x00CD, 0x00CC, 0x00EC, 0x00D2, 0x00F2, 0x00D5, 0x00F5, 0x007B, 0x007D, 0x005C, 0x007C},
138  /*07*/ {0x007C, 0x005E, 0x005F, 0x007C, 0x007E, 0x0020, 0x0020, 0x00C4, 0x00E4, 0x00D6, 0x00F6, 0x00DF, 0x00A5, 0x00A4, 0x007C, 0x00C5,
139  0x00E5, 0x00D8, 0x00F8, 0x00C4, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x007C},
140  /*08*/ {0x007C, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020,
141  0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x007C},
142  /*09*/ {0x007C, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003A, 0x003B, 0x003C, 0x003D, 0x003E,
143  0x003F, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004A, 0x004B, 0x004C, 0x004D, 0x007C},
144  /*10*/ {0x007C, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x005B, 0x005D,
145  0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x007C},
146  /*11*/ {0x007C, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007A, 0x0020, 0x00E1, 0x00E9, 0x00ED,
147  0x00F3, 0x00FA, 0x00E7, 0x00F7, 0x00D1, 0x00E1, 0x00F1, 0x2588, 0x00AE, 0x00B0, 0x00BD, 0x00BF, 0x2122, 0x00A2, 0x00A3, 0x007C},
148  /*12*/ {0x007C, 0x266A, 0x00E0, 0x00A0, 0x00E8, 0x00E2, 0x00EA, 0x00EE, 0x00F4, 0x00FB, 0x00C1, 0x00C9, 0x00D3, 0x00DA, 0x00DC, 0x00FC,
149  0x2018, 0x00A1, 0x002A, 0x2019, 0x2014, 0x00A9, 0x2120, 0x2022, 0x201C, 0x201D, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x007C},
150  /*13*/ {0x007C, 0x00C0, 0x00C2, 0x00C7, 0x00C8, 0x00CA, 0x00CB, 0x00EB, 0x00CE, 0x00CF, 0x00EF, 0x00D4, 0x00D9, 0x00F9, 0x00DB, 0x00AB,
151  0x00BB, 0x0020, 0x0020, 0x00C3, 0x00E3, 0x00CD, 0x00CC, 0x00EC, 0x00D2, 0x00F2, 0x00D5, 0x00F5, 0x007B, 0x007D, 0x005C, 0x007C},
152  /*14*/ {0x007C, 0x005E, 0x005F, 0x007C, 0x007E, 0x0020, 0x0020, 0x00C4, 0x00E4, 0x00D6, 0x00F6, 0x00DF, 0x00A5, 0x00A4, 0x007C, 0x00C5,
153  0x00E5, 0x00D8, 0x00F8, 0x00C4, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x0020, 0x007C},
154  /*15*/ {0x2514, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014,
155  0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2014, 0x2518}};
156  #endif // 0
157 #endif // defined (INCLUDE_AJACC)
158 
159 
160 void NTV2FrameGrabber::ClearCaptionBuffer (const bool inNotifyClients)
161 {
162  #if defined (INCLUDE_AJACC)
163  for (UWord row (NTV2_CC608_MinRow); row <= NTV2_CC608_MaxRow; row++)
164  for (UWord col (NTV2_CC608_MinCol); col <= NTV2_CC608_MaxCol; col++)
165  mScreenBuffer [row-1][col-1] = 0x0020; // gTest[row-1][col-1];
166  if (inNotifyClients)
167  emit captionScreenChanged (&mScreenBuffer[0][0]);
168  #else
169  (void) inNotifyClients;
170  #endif
171 }
172 
173 
175 {
176  #if defined (INCLUDE_AJACC)
177  NTV2_ASSERT (mNTV2Card.IsOpen ());
178  NTV2_ASSERT (mDeviceID != DEVICE_ID_NOTFOUND);
179 
180  if (mNTV2Card.features().CanDoCustomAnc())
181  {
182  bool gotCaptionPacket (false);
183  CaptionData captionData; // The two byte pairs (one pair per field) our 608 decoder is looking for
184  ostringstream oss; // DEBUG
185 
186  // See what's in the AUTOCIRCULATE_TRANSFER's F1 & F2 anc buffers...
187  AJAAncillaryList ancPacketsF1, ancPacketsF2;
188  ancPacketsF1.AddReceivedAncillaryData ((uint8_t *) mTransferStruct.acANCBuffer.GetHostPointer (), mTransferStruct.acANCBuffer.GetByteCount ());
189  ancPacketsF2.AddReceivedAncillaryData ((uint8_t *) mTransferStruct.acANCField2Buffer.GetHostPointer (), mTransferStruct.acANCField2Buffer.GetByteCount ());
190  ancPacketsF1.ParseAllAncillaryData ();
191  ancPacketsF2.ParseAllAncillaryData ();
192 
194  {
196  if (ancCEA708DataIn.GetPayloadData () && ancCEA708DataIn.GetPayloadByteCount ())
197  gotCaptionPacket = m708Decoder ? m708Decoder->SetSMPTE334AncData (ancCEA708DataIn.GetPayloadData (), ancCEA708DataIn.GetPayloadByteCount ()) : false;
198  //if (gotCaptionPacket) oss << "Using F1 AJAAnc CEA708 packet(s)";
199  }
201  {
203  if (ancCEA608DataIn.GetPayloadData () && ancCEA608DataIn.GetPayloadByteCount ())
204  gotCaptionPacket = m708Decoder ? m708Decoder->SetSMPTE334AncData (ancCEA608DataIn.GetPayloadData (), ancCEA608DataIn.GetPayloadByteCount ()) : false;
205  //if (gotCaptionPacket) oss << "Using F1 AJAAnc CEA608 packet(s)";
206  }
208  {
210  if (AJA_SUCCESS (ancEIA608DataIn.ParsePayloadData ()))
211  if (AJA_SUCCESS (ancEIA608DataIn.GetCEA608Bytes (captionData.f1_char1, captionData.f1_char2, captionData.bGotField1Data)))
212  gotCaptionPacket = true;
213  //if (gotCaptionPacket) oss << "Using F1 AJAAnc EIA608 packet(s)";
214  }
216  {
218  if (AJA_SUCCESS (ancEIA608DataIn.ParsePayloadData ()))
219  if (AJA_SUCCESS (ancEIA608DataIn.GetCEA608Bytes (captionData.f2_char1, captionData.f2_char2, captionData.bGotField2Data)))
220  gotCaptionPacket = true;
221  //if (gotCaptionPacket) oss << "Using F2 AJAAnc EIA608 packet(s)";
222  }
223 
224  if (NTV2_IS_HD_VIDEO_FORMAT (mCurrentVideoFormat))
225  {
226  if (gotCaptionPacket && m708Decoder && m708Decoder->ParseSMPTE334AncPacket ())
227  captionData = m708Decoder->GetCC608CaptionData (); // Extract the 608 caption byte pairs
228  } // else if HD
229 
230  // Sorry, we only handle 608 captions -- nothing else.
231  // The 608 decoder does the rest. It expects to be called once per frame (to implement flashing characters and roll-up).
232  // Pass the caption byte pairs to it for processing (even if captionData.HasData returns false)...
233  if (m608Decoder)
234  m608Decoder->ProcessNew608FrameData (captionData);
235  //if (!oss.str ().empty ()) cerr << oss.str () << endl; // DEBUG DEBUG DEBUG DEBUG
236  //if (captionData.HasData ()) cerr << captionData << endl;
237  } // if able to use Anc buffers
238  #endif // defined (INCLUDE_AJACC)
239 } // GrabCaptions
240 
241 
242 void NTV2FrameGrabber::changeCaptionChannel (int inNewCaptionChannelId)
243 {
244  #if defined (INCLUDE_AJACC)
245  const NTV2Line21Channel chosenCaptionChannel (static_cast <NTV2Line21Channel> (inNewCaptionChannelId));
246 
247  if (!m608Decoder && IsValidLine21Channel (chosenCaptionChannel))
248  {
249  NTV2_ASSERT (!m708Decoder);
250  if (CNTV2CaptionDecoder608::Create (m608Decoder) && CNTV2CaptionDecoder708::Create (m708Decoder))
251  {
252  m608Decoder->SubscribeChangeNotification (Caption608Changed, this);
253  m608Decoder->SetDisplayChannel (chosenCaptionChannel);
254  ClearCaptionBuffer (true);
255  }
256  else
257  {m608Decoder = AJA_NULL; m708Decoder = AJA_NULL;}
258  }
259  else if (m608Decoder)
260  {
261  NTV2_ASSERT (m708Decoder);
262  if (!IsValidLine21Channel (chosenCaptionChannel))
263  {m608Decoder = AJA_NULL; m708Decoder = AJA_NULL;}
264  else if (m608Decoder->GetDisplayChannel () != chosenCaptionChannel)
265  m608Decoder->SetDisplayChannel (chosenCaptionChannel);
266  ClearCaptionBuffer (true);
267  }
268  #else
269  (void) inNewCaptionChannelId;
270  #endif // defined (INCLUDE_AJACC)
271 } // changeCaptionChannel
272 
273 
275 {
276  // Set up 2 images to ping-pong between capture and display...
277  QImage * images [NTV2_NUM_IMAGES];
278  ULWord framesCaptured (0);
279  FGNOTE("Thread started");
280 
281  // Initialize images
282  for (int i(0); i < NTV2_NUM_IMAGES; i++)
283  images[i] = new QImage(QTPREVIEW_WIDGET_X, QTPREVIEW_WIDGET_Y, QImage::Format_RGB32);
284 
285  // Make sure all Bidirectionals are set to Inputs.
286  if (mNTV2Card.Open(mBoardNumber))
287  {
288  if (!mDoMultiChannel && !mNTV2Card.AcquireStreamForApplicationWithReference (kDemoAppSignature, int32_t(AJAProcess::GetPid())))
289  {
290  // We have not acquired the board continue until something changes...
291  FGWARN("Could not acquire " << mNTV2Card.GetDescription());
292  mNTV2Card.Close ();
293  mDeviceID = DEVICE_ID_NOTFOUND;
294  }
295  else
296  {
297  mNTV2Card.GetTaskMode (mSavedTaskMode); // Save the current state before we change it
298  mNTV2Card.SetTaskMode (NTV2_OEM_TASKS); // Since this is an OEM demo we will set the OEM service level
299 
300  if (mNTV2Card.features().HasBiDirectionalSDI()) // If device has bidirectional SDI connectors...
301  {
302  bool waitForInput = false;
303  for (unsigned offset(0); offset < 8; offset++)
304  {
305  mNTV2Card.EnableChannel (NTV2Channel(offset));
306  bool outputEnabled;
307  mNTV2Card.GetSDITransmitEnable (NTV2Channel(offset), outputEnabled);
308  if (outputEnabled)
309  {
310  waitForInput = true;
311  mNTV2Card.SetSDITransmitEnable (NTV2Channel(offset), false);
312  }
313  }
314  // Only if we had to change an output to input do we need to wait.
315  if (waitForInput)
316  mNTV2Card.WaitForInputVerticalInterrupt (mChannel, 10); // ...and give the device some time to lock to a signal
317  }
318  }
319  }
320 
321  while (true)
322  {
323  if (mAbort)
324  break;
325 
326  if (!NTV2_IS_VALID_INPUT_SOURCE(mInputSource))
327  {
328  // No input chosen, so display banner...
329  if (NTV2_IS_VALID_CHANNEL(mChannel))
331  QImage * currentImage (images[framesCaptured % NTV2_NUM_IMAGES]);
332  currentImage->load (":/resources/splash.png");
333  emit newStatusString ("");
334  emit newFrame (*currentImage, true);
335  AJATime::Sleep(200);
336  continue;
337  }
338 
339  if (mRestart)
340  {
341  gMutex.lock();
343  if (mNTV2Card.IsOpen())
344  {
345  if (!mDoMultiChannel)
346  {
348  mNTV2Card.SetTaskMode (mSavedTaskMode);
349  }
350  mNTV2Card.Close();
351  mDeviceID = DEVICE_ID_NOTFOUND;
352  }
353  gMutex.unlock();
354 
355  if (mNTV2Card.Open(mBoardNumber))
356  {
357  if (!mDoMultiChannel && !mNTV2Card.AcquireStreamForApplicationWithReference (kDemoAppSignature, int32_t(AJAProcess::GetPid())))
358  {
359  // Haven't acquired the device --- continue til other app releases it...
360  FGWARN(mNTV2Card.GetDisplayName() << " is busy");
361  QImage * currentImage (images[framesCaptured % NTV2_NUM_IMAGES]);
362  currentImage->fill(Qt::lightGray);
363  QString status (QString("%1 is busy").arg(mNTV2Card.GetDisplayName().c_str()));
364  emit newStatusString(status);
365  emit newFrame(*currentImage, true);
366  mNTV2Card.Close();
367  mDeviceID = DEVICE_ID_NOTFOUND;
368  AJATime::Sleep(500);
369  continue;
370  }
371 
372  mNTV2Card.GetTaskMode(mSavedTaskMode); // Save the current state before we change it
373  mNTV2Card.SetTaskMode(NTV2_OEM_TASKS); // Since this is an OEM demo we will set the OEM service level
374 
375  mDeviceID = mNTV2Card.GetDeviceID();
376  if (mNTV2Card.features().CanDoMultiFormat())
377  mNTV2Card.SetMultiFormatMode(true);
378 
379  if (!mNTV2Card.IsDeviceReady(false))
380  {
381  FGWARN(mNTV2Card.GetDisplayName() << " not ready");
382  QImage * currentImage (images[framesCaptured % NTV2_NUM_IMAGES]);
383  currentImage->fill(Qt::lightGray);
384  QString status (QString("%1 is not ready").arg(mNTV2Card.GetDisplayName().c_str()));
385  emit newStatusString(status);
386  emit newFrame(*currentImage, true);
387  AJATime::Sleep(1000); // Keep the UI responsive while waiting for device to become ready
388  }
389  else if (!mNTV2Card.features().CanDoCapture())
390  {
391  FGWARN(mNTV2Card.GetDisplayName() << " is output-only device");
392  QImage * currentImage (images[framesCaptured % NTV2_NUM_IMAGES]);
393  currentImage->fill(qRgba(40, 40, 40, 255));
394  QString status (QString("%1 is output-only device").arg(mNTV2Card.GetDisplayName().c_str()));
395  emit newStatusString(status);
396  emit newFrame(*currentImage, true);
397  AJATime::Sleep(1000); // Keep the UI responsive
398  }
399  else if (!mNTV2Card.features().GetNumCSCs())
400  {
401  FGWARN(mNTV2Card.GetDisplayName() << " has no CSCs, won't work with NTV2FrameGrabber");
402  QImage * currentImage (images[framesCaptured % NTV2_NUM_IMAGES]);
403  currentImage->fill(qRgba(40, 40, 40, 255));
404  QString status (QString("%1 has no CSCs, won't work for this demo").arg(mNTV2Card.GetDisplayName().c_str()));
405  emit newStatusString(status);
406  emit newFrame(*currentImage, true);
407  AJATime::Sleep(1000); // Keep the UI responsive
408  }
409  else if (SetupInput())
410  {
411  mTransferStruct.acANCBuffer.Allocate (mNTV2Card.features().CanDoCustomAnc() ? NTV2_ANCSIZE_MAX : 0); // Reserve space for anc data
412  mTransferStruct.acANCField2Buffer.Allocate(mNTV2Card.features().CanDoCustomAnc() ? NTV2_ANCSIZE_MAX : 0); // Reserve space for anc data
413  const ULWord acOptions(AUTOCIRCULATE_WITH_RP188 | (mTransferStruct.acANCBuffer.IsNULL() && mTransferStruct.acANCField2Buffer.IsNULL() ? 0 : AUTOCIRCULATE_WITH_ANC));
414  gMutex.lock();
416  mNTV2Card.AutoCirculateInitForInput (mChannel, NTV2ACFrameRange(7), ::NTV2ChannelToAudioSystem(mChannel), acOptions);
417  gMutex.unlock();
418  SetupAudio();
419  if (mAudioOutput)
420  mAudioDevice = mAudioOutput->start();
421 
422  // Start AutoCirculate...
423  mNTV2Card.SetLTCInputEnable(true);
424  mNTV2Card.SetRP188SourceFilter (mChannel, 0); // 0=LTC 1=VITC1 2=VITC2
425  mNTV2Card.AutoCirculateStart(mChannel);
426 
427  for (int i(0); i < NTV2_NUM_IMAGES; i++)
428  {
429  delete images[i];
430  images[i] = new QImage (mFrameDimensions.width(), mFrameDimensions.height(), QImage::Format_RGB32);
431  }
432 
433  framesCaptured = 0;
434  mRestart = false;
435  } // if board set up ok
436  else
437  AJATime::Sleep(1000); // This keeps the UI responsive if/while this channel has no input
438  } // if board opened ok
439  else
440  {
441  FGWARN("Open failed for device " << DEC(GetDeviceIndex()));
442  AJATime::Sleep(200);
443  continue;
444  }
445 
446  emit newStatusString(::NTV2InputSourceToString (mInputSource, true).c_str());
447  } // if mRestart
448 
449  if (!CheckForValidInput() && NTV2_IS_VALID_INPUT_SOURCE(mInputSource))
450  {
451  QImage * currentImage (images[framesCaptured % NTV2_NUM_IMAGES]);
452  currentImage->fill(qRgba(40, 40, 40, 255));
453  QString status (QString("%1: No Detected Input").arg(::NTV2InputSourceToString(mInputSource, true).c_str()));
454  emit newStatusString(status);
455  emit newFrame(*currentImage, true);
456  AJATime::Sleep(200);
457  continue;
458  }
459 
460  AUTOCIRCULATE_STATUS acStatus;
461  mNTV2Card.AutoCirculateGetStatus (mChannel, acStatus);
462  if (acStatus.acState == NTV2_AUTOCIRCULATE_RUNNING && acStatus.acBufferLevel > 1)
463  {
464  QImage * currentImage (images [framesCaptured % NTV2_NUM_IMAGES]);
465  NTV2TimeCodeList tcValues;
466 
467  #if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
468  mTransferStruct.SetVideoBuffer (reinterpret_cast<PULWord>(currentImage->bits()), ULWord(currentImage->sizeInBytes()));
469  #else
470  mTransferStruct.SetVideoBuffer (reinterpret_cast<PULWord>(currentImage->bits()), ULWord(currentImage->byteCount()));
471  #endif
472  mNTV2Card.AutoCirculateTransfer (mChannel, mTransferStruct);
473  if (!mFormatIsProgressive && mDeinterlace)
474  {
475  // Eliminate field flicker by copying even lines to odd lines...
476  // (a very lame de-interlace technique)
477  if (currentImage->height() == int(mFrameDimensions.height()) && currentImage->width() == int(mFrameDimensions.width()))
478  for (ULWord line (0); line < mFrameDimensions.height(); line += 2)
479  ::memcpy (currentImage->scanLine (int(line) + 1), currentImage->scanLine(int(line)), mFrameDimensions.width() * 4);
480  }
481  GrabCaptions();
482  mTimeCode.clear ();
483  if (mTransferStruct.acTransferStatus.acFrameStamp.GetInputTimeCodes(tcValues) && size_t(mTimeCodeSource) < tcValues.size())
484  {
485  CRP188 tc (tcValues.at(mTimeCodeSource));
486  if (!tcValues.at (mTimeCodeSource).IsValid())
487  {
488  // If the requested timecode was invalid, check for embedded LTC
489  if (NTV2_IS_VALID_INPUT_SOURCE(mInputSource))
490  tc.SetRP188 (tcValues.at (::NTV2InputSourceToTimecodeIndex (mInputSource, true)));
491  }
492  tc.GetRP188Str (mTimeCode);
493  }
494 
495  QString outString (::NTV2InputSourceToString (mInputSource, true).c_str());
496  outString.append (" ");
497  outString.append (::NTV2VideoFormatToString (mCurrentVideoFormat).c_str ());
498  outString.append (" ");
499  outString.append (mTimeCode.c_str());
500 
501  emit newStatusString (outString);
502 
503  emit newFrame (*currentImage, (framesCaptured == 0) ? true : false);
504  if (mbWithAudio && mTransferStruct.acAudioBuffer)
505  OutputAudio (mTransferStruct.acAudioBuffer, mTransferStruct.acTransferStatus.acAudioTransferSize);
506 
507  framesCaptured++;
508  } // if running and at least one frame ready to transfer
509  else
510  mNTV2Card.WaitForInputVerticalInterrupt (mChannel);
511  } // loop til break
512 
513  if (mNTV2Card.IsOpen ())
514  {
515  gMutex.lock();
517  if (!mDoMultiChannel)
518  {
519  mNTV2Card.ReleaseStreamForApplicationWithReference (kDemoAppSignature, int32_t(AJAProcess::GetPid())); // Release the device
520  mNTV2Card.SetTaskMode(mSavedTaskMode); // Restore prior task mode
521  }
522  gMutex.unlock();
523  }
524 
525  for (int i(0); i < NTV2_NUM_IMAGES; i++)
526  delete images[i];
527 
528  FGNOTE("Thread completed, will exit for " << mNTV2Card.GetDisplayName() << " input " << ::NTV2InputSourceToString(mInputSource));
529 
530 } // run
531 
532 
534 {
535  if (!mNTV2Card.IsOpen())
536  return false;
537  if (mDeviceID == DEVICE_ID_NOTFOUND)
538  return false;
539 
540  mChannel = ::NTV2InputSourceToChannel(mInputSource);
541  if (mChannel == NTV2_CHANNEL_INVALID)
542  mChannel = NTV2_CHANNEL1;
543  mTimeCodeSource = ::NTV2InputSourceToTimecodeIndex(mInputSource);
544 
545  bool waitForInput(false);
546  if (mNTV2Card.features().HasBiDirectionalSDI()) // If device has bidirectional SDIs...
547  for (unsigned offset(0); offset < 4; offset++)
548  {
549  mNTV2Card.EnableChannel(NTV2Channel(mChannel + offset));
550  bool outputEnabled;
551  mNTV2Card.GetSDITransmitEnable (NTV2Channel(mChannel + offset), outputEnabled);
552  if (outputEnabled)
553  {
554  waitForInput = true;
555  mNTV2Card.SetSDITransmitEnable (NTV2Channel(mChannel + offset), false);
556  }
557  }
558 
559  // Only if we had to change an output to input do we need to wait.
560  if (waitForInput)
561  mNTV2Card.WaitForInputVerticalInterrupt (mChannel, 10); // Give the device ~10 fields/frames to lock to a signal
562 
563  mCurrentVideoFormat = GetVideoFormatFromInputSource();
564  mCurrentColorSpace = GetColorSpaceFromInputSource();
565  mFrameDimensions.set (QTPREVIEW_WIDGET_X, QTPREVIEW_WIDGET_Y);
566  if (!NTV2_IS_VALID_VIDEO_FORMAT(mCurrentVideoFormat))
567  return false; // No video!
568 
569  mNTV2Card.SetVideoFormat (mCurrentVideoFormat, false, false, mChannel);
571  mNTV2Card.GetVANCMode (vm, mChannel);
572  const NTV2FormatDescriptor fd (mCurrentVideoFormat, mFrameBufferFormat, vm);
573  mFrameDimensions.set (fd.GetRasterWidth(), fd.GetRasterHeight());
574  const QString vfString (::NTV2VideoFormatToString(mCurrentVideoFormat).c_str());
575  FGDBG("mInputSource=" << mChannel << " mCurrentVideoFormat=" << vfString.toStdString()
576  << " wdth=" << mFrameDimensions.width() << " hght=" << mFrameDimensions.height());
577 
578  mFormatIsProgressive = IsProgressivePicture(mCurrentVideoFormat);
579  if (!mbFixedReference)
581 
582  if (NTV2_INPUT_SOURCE_IS_SDI(mInputSource))
583  {
584  mNumChannels = 0;
585  mTsi = false;
586 
587  bool is6g(false), is12g(false);
588  mNTV2Card.GetSDIInput6GPresent(is6g, mChannel);
589  mNTV2Card.GetSDIInput12GPresent(is12g, mChannel);
590 
591  if (mNTV2Card.features().CanDo12gRouting() && (is6g || is12g))
592  {
593  mNTV2Card.Connect (::GetCSCInputXptFromChannel(mChannel), ::GetSDIInputOutputXptFromChannel(mChannel));
594  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(mChannel), ::GetCSCOutputXptFromChannel (mChannel, false/*isKey*/, true/*isRGB*/));
595  mNTV2Card.SetFrameBufferFormat (mChannel, mFrameBufferFormat);
596  mNTV2Card.EnableChannel(mChannel);
597  mNTV2Card.SetSDIInLevelBtoLevelAConversion (mChannel, IsInput3Gb(mInputSource) ? true : false);
598  }
599  else for (unsigned offset(0); offset < 4; offset++)
600  {
601  mNumChannels++;
602  mNTV2Card.Connect (::GetCSCInputXptFromChannel (NTV2Channel(mChannel + offset)), ::GetSDIInputOutputXptFromChannel(NTV2Channel(mChannel + offset)));
603  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel (NTV2Channel(mChannel + offset)), ::GetCSCOutputXptFromChannel(NTV2Channel(mChannel + offset), false/*isKey*/, true/*isRGB*/));
604  mNTV2Card.SetFrameBufferFormat (NTV2Channel(mChannel + offset), mFrameBufferFormat);
605  mNTV2Card.EnableChannel (NTV2Channel(mChannel + offset));
606  mNTV2Card.SetSDIInLevelBtoLevelAConversion (mChannel + offset, IsInput3Gb(mInputSource) ? true : false);
607  if (!NTV2_IS_4K_VIDEO_FORMAT(mCurrentVideoFormat))
608  break;
609  mNTV2Card.Set4kSquaresEnable(true, NTV2_CHANNEL1);
610  }
611  }
612  else if (mInputSource == NTV2_INPUTSOURCE_ANALOG1)
613  {
614  mNumChannels = 0;
615  mTsi = false;
616  //mNTV2Card.SetTsiFrameEnable(false, NTV2_CHANNEL1);
617 
619  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(NTV2_CHANNEL1), ::GetCSCOutputXptFromChannel(NTV2_CHANNEL1, false/*isKey*/, true/*isRGB*/));
620  mNTV2Card.SetFrameBufferFormat(NTV2_CHANNEL1, mFrameBufferFormat);
621  if (!mbFixedReference)
623  mChannel = NTV2_CHANNEL1;
624  mNumChannels = 1;
625  }
626  else if (NTV2_INPUT_SOURCE_IS_HDMI(mInputSource))
627  {
628  mNumChannels = 0;
629  mTsi = false;
630 
631  if (!mbFixedReference)
632  mNTV2Card.SetReference(::NTV2InputSourceToReferenceSource(mInputSource));
633 
634  // configure hdmi with 2.0 support
635  if (mNTV2Card.features().CanDo12gRouting())
636  {
637  mNumChannels = 1;
638  mNTV2Card.EnableChannel(mChannel);
639  mNTV2Card.SetMode (mChannel, NTV2_MODE_CAPTURE);
640  mNTV2Card.SetFrameBufferFormat (mChannel, mFrameBufferFormat);
641  if (mCurrentColorSpace == NTV2_LHIHDMIColorSpaceYCbCr)
642  {
643  mNTV2Card.Connect (::GetCSCInputXptFromChannel(mChannel),
644  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, false/*isHDMI_RGB*/, 0/*hdmiQuadrant*/));
645  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(mChannel),
646  ::GetCSCOutputXptFromChannel (mChannel, false/*isKey*/, true/*isRGB*/));
647  }
648  else
649  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(mChannel),
650  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, true/*isHDMI_RGB*/, 0/*hdmiQuadrant*/));
651  }
652  else if (NTV2_IS_4K_VIDEO_FORMAT(mCurrentVideoFormat) && !mNTV2Card.features().CanDoHDMIQuadRasterConversion())
653  {
654  // Set two sample interleave
655  mChannel = NTV2_CHANNEL1;
656  mNTV2Card.SetTsiFrameEnable(true, NTV2_CHANNEL1);
657 
658  for (NTV2Channel channel (NTV2_CHANNEL1); channel < NTV2_CHANNEL3; channel = NTV2Channel(channel+1))
659  {
660  mNTV2Card.EnableChannel(channel);
661  mNTV2Card.SetMode (channel, NTV2_MODE_CAPTURE);
662  mNTV2Card.SetFrameBufferFormat (channel, mFrameBufferFormat);
663  }
664 
665  if (mCurrentColorSpace == NTV2_LHIHDMIColorSpaceYCbCr)
666  {
667  mNTV2Card.Connect (NTV2_XptCSC1VidInput,
668  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, false/*isHDMI_RGB*/, NTV2_CHANNEL1/*hdmiQuadrant*/));
669  mNTV2Card.Connect (NTV2_XptCSC2VidInput,
670  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, false/*isHDMI_RGB*/, NTV2_CHANNEL2/*hdmiQuadrant*/));
671  mNTV2Card.Connect (NTV2_XptCSC3VidInput,
672  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, false/*isHDMI_RGB*/, NTV2_CHANNEL3/*hdmiQuadrant*/));
673  mNTV2Card.Connect (NTV2_XptCSC4VidInput,
674  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, false/*isHDMI_RGB*/, NTV2_CHANNEL4/*hdmiQuadrant*/));
675 
680  }
681  else
682  {
683  mNTV2Card.Connect (NTV2_Xpt425Mux1AInput, ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, true/*isHDMI_RGB*/, NTV2_CHANNEL1/*hdmiQuadrant*/));
684  mNTV2Card.Connect (NTV2_Xpt425Mux1BInput, ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, true/*isHDMI_RGB*/, NTV2_CHANNEL2/*hdmiQuadrant*/));
685  mNTV2Card.Connect (NTV2_Xpt425Mux2AInput, ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, true/*isHDMI_RGB*/, NTV2_CHANNEL3/*hdmiQuadrant*/));
686  mNTV2Card.Connect (NTV2_Xpt425Mux2BInput, ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, true/*isHDMI_RGB*/, NTV2_CHANNEL4/*hdmiQuadrant*/));
687  }
688 
693 
694  mNumChannels = 2;
695  mTsi = true;
696  } // if 4K and can't do HDMI quad raster conversion
697  else if (NTV2_IS_4K_VIDEO_FORMAT(mCurrentVideoFormat) && mNTV2Card.features().CanDoHDMIQuadRasterConversion())
698  {
699  mNumChannels = 0;
700  mNTV2Card.SetTsiFrameEnable(false, NTV2_CHANNEL1);
701  for (NTV2Channel channel(NTV2_CHANNEL1); channel < NTV2_CHANNEL5; channel = NTV2Channel(channel+1))
702  {
703  mNumChannels++;
704  mNTV2Card.EnableChannel(channel);
705  mNTV2Card.SetMode (channel, NTV2_MODE_CAPTURE);
706  mNTV2Card.SetFrameBufferFormat (channel, mFrameBufferFormat);
707  if (mCurrentColorSpace == NTV2_LHIHDMIColorSpaceYCbCr)
708  {
709  mNTV2Card.Connect (::GetCSCInputXptFromChannel(channel),
710  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, false/*isHDMI_RGB*/, channel/*hdmiQuadrant*/));
711  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(channel),
712  ::GetCSCOutputXptFromChannel (channel, false/*isKey*/, true/*isRGB*/));
713  }
714  else
715  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(channel),
716  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, true/*isHDMI_RGB*/, channel/*hdmiQuadrant*/));
717  } // loop once for each channel (4 times for 4K/UHD)
718  } // else if 4K and can do HDMI quad raster conversion
719  else
720  {
721  mNumChannels = 1;
722  mNTV2Card.EnableChannel(mChannel);
723  mNTV2Card.SetMode (mChannel, NTV2_MODE_CAPTURE);
724  mNTV2Card.SetFrameBufferFormat (mChannel, mFrameBufferFormat);
725  if (mCurrentColorSpace == NTV2_LHIHDMIColorSpaceYCbCr)
726  {
727  mNTV2Card.Connect (::GetCSCInputXptFromChannel(mChannel),
728  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, false/*isHDMI_RGB*/, 0/*hdmiQuadrant*/));
729  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(mChannel),
730  ::GetCSCOutputXptFromChannel (mChannel, false/*isKey*/, true/*isRGB*/));
731  }
732  else
733  mNTV2Card.Connect (::GetFrameStoreInputXptFromChannel(mChannel),
734  ::GetInputSourceOutputXpt (mInputSource, false/*isSDI_DS2*/, true/*isHDMI_RGB*/, 0/*hdmiQuadrant*/));
735  } // else not 4K
736 
737  // configure the qrc if present
738  if (mNTV2Card.features().GetHDMIVersion() == 2)
740  }
741  else
742  FGWARN("Bad mInputSource value " << DEC(mInputSource));
743 
744  return true;
745 
746 } // SetupInput
747 
748 
750 {
751  if (mNTV2Card.IsOpen())
752  {
753  mNTV2Card.AutoCirculateStop(mChannel);
754 
755  bool tsiEnable(false);
756  mNTV2Card.GetTsiFrameEnable (tsiEnable, NTV2_CHANNEL1);
757  for (ULWord i(0); i < (tsiEnable ? 2 : mNumChannels); i++)
758  mNTV2Card.SetMode (NTV2Channel(mChannel + i), NTV2_MODE_DISPLAY);
759  }
760  ClearCaptionBuffer(true);
761 
762 } // StopAutoCirculate
763 
764 
766 {
769 
770  if (videoFormat == NTV2_FORMAT_UNKNOWN)
771  {
772  mCurrentVideoFormat = videoFormat;
773  return false;
774  } // if no video or unknown format
775 
776  if ((mCurrentVideoFormat != videoFormat) || (mCurrentColorSpace != colorSpace))
777  {
778  if (mDebounceCounter == 0)
779  {
780  // Check to see if the video input has stabilized...
781  mLastVideoFormat = videoFormat;
782  mDebounceCounter++;
783  }
784  else if (mDebounceCounter == 6)
785  {
786  // The new format is stable -- restart autocirculate...
787  mRestart = true;
788  mCurrentVideoFormat = videoFormat;
789  mDebounceCounter = 0;
790  }
791  else
792  {
793  if (mLastVideoFormat == videoFormat)
794  mDebounceCounter++; // New format still stable -- keep counting
795  else
796  mDebounceCounter = 0; // Input changed again -- start over
797  }
798  return true;
799  } // if video format changed
800 
801  return true;
802 
803 } // CheckForValidInput
804 
805 
807 {
808  if (!mNTV2Card.IsOpen())
809  return NTV2_FORMAT_UNKNOWN;
810  if (mDeviceID == DEVICE_ID_NOTFOUND)
811  return NTV2_FORMAT_UNKNOWN;
812 
814  if (NTV2_INPUT_SOURCE_IS_SDI(mInputSource))
815  {
816  bool is6g (false), is12g(false);
817  NTV2Channel channel (::NTV2InputSourceToChannel(mInputSource));
818  mNTV2Card.GetSDIInput6GPresent(is6g, channel);
819  mNTV2Card.GetSDIInput12GPresent(is12g, channel);
820  if (mNTV2Card.features().CanDo12gRouting() && (is6g || is12g))
821  {
822  videoFormat = mNTV2Card.GetInputVideoFormat(mInputSource);
823  return videoFormat;
824  }
825  }
826 
827  switch (mInputSource)
828  {
831  {
832  const ULWord ndx (::GetIndexForNTV2InputSource(mInputSource));
833  videoFormat = mNTV2Card.GetInputVideoFormat(::GetNTV2InputSourceForIndex(ndx + 0));
834  NTV2Standard videoStandard (::GetNTV2StandardFromVideoFormat(videoFormat));
835  if (mCheckFor4K && (videoStandard == NTV2_STANDARD_1080p))
836  {
837  NTV2VideoFormat videoFormatNext (mNTV2Card.GetInputVideoFormat(::GetNTV2InputSourceForIndex(ndx + 1)));
838  if (videoFormatNext == videoFormat)
839  {
840  videoFormatNext = mNTV2Card.GetInputVideoFormat(::GetNTV2InputSourceForIndex(ndx + 2));
841  if (videoFormatNext == videoFormat)
842  {
843  videoFormatNext = mNTV2Card.GetInputVideoFormat(::GetNTV2InputSourceForIndex(ndx + 3));
844  if (videoFormatNext == videoFormat)
846  }
847  }
848  }
849  }
850  break;
851 
853  break; // indicates no source is currently selected
854 
855  default:
856  videoFormat = mNTV2Card.GetInputVideoFormat(mInputSource);
857  break;
858  }
859  return videoFormat;
860 
861 } // GetVideoFormatFromInputSource
862 
863 
865 {
866  if (NTV2_INPUT_SOURCE_IS_HDMI(mInputSource))
867  {
869  mNTV2Card.GetHDMIInputColor (hdmiColor, mChannel);
870  return hdmiColor;
871  }
873 }
874 
875 
877 {
878  bool is3Gb(false);
879  mNTV2Card.GetSDIInput3GbPresent (is3Gb, ::NTV2InputSourceToChannel(inputSource));
880  return is3Gb;
881 } // IsInput3Gb
882 
883 
885 {
886  if (!mNTV2Card.IsOpen())
887  return;
888  if (mDeviceID == DEVICE_ID_NOTFOUND)
889  return;
890 
891  mTransferStruct.acAudioBuffer.Allocate(NTV2_AUDIOSIZE_MAX); // Reserve space for largest audio packet/frame
892  if (mAudioOutput)
893  {
894  delete mAudioOutput;
895  mAudioOutput = AJA_NULL;
896  }
897 
898  NTV2AudioSource audioSource (NTV2_AUDIO_EMBEDDED);
899  if (NTV2_INPUT_SOURCE_IS_HDMI(mInputSource))
900  audioSource = NTV2_AUDIO_HDMI;
901  else if (NTV2_INPUT_SOURCE_IS_ANALOG(mInputSource))
902  audioSource = NTV2_AUDIO_ANALOG;
903 
904  // Set up AJA device audio...
905  mNumAudioChannels = mNTV2Card.features().GetMaxAudioChannels();
906  mAudioSystem = ::NTV2ChannelToAudioSystem(mChannel);
907  mNTV2Card.SetAudioSystemInputSource (mAudioSystem, audioSource, ::NTV2InputSourceToEmbeddedAudioInput(mInputSource));
908  mNTV2Card.SetNumberAudioChannels (mNumAudioChannels, mAudioSystem);
909  mNTV2Card.SetAudioRate (NTV2_AUDIO_48K, mAudioSystem);
910  mNTV2Card.SetAudioBufferSize (NTV2_AUDIO_BUFFER_BIG, mAudioSystem);
911 
912  // Set up Qt's audio output...
913 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
914  mFormat.setSampleRate(48000);
915  mFormat.setChannelCount(2);
916  mFormat.setSampleSize(16);
917  mFormat.setCodec("audio/pcm");
918  mFormat.setByteOrder(QAudioFormat::LittleEndian);
919  mFormat.setSampleType(QAudioFormat::SignedInt);
920 #else
921  mFormat.setSampleRate(48000);
922  mFormat.setChannelCount(2);
923  mFormat.setSampleFormat(QAudioFormat::Int16);
924 #endif
925 
926 #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
927  QAudioDeviceInfo audioDeviceInfo (QAudioDeviceInfo::defaultOutputDevice());
928  if (audioDeviceInfo.isFormatSupported(mFormat))
929  mAudioOutput = new QAudioOutput (mFormat, AJA_NULL);
930 #else
931  QAudioDevice deviceInfo (QMediaDevices::defaultAudioOutput());
932  if (deviceInfo.isFormatSupported(mFormat))
933  mAudioOutput = new QAudioSink(deviceInfo, mFormat, AJA_NULL);
934 #endif
935 } // SetupAudio
936 
937 
938 void NTV2FrameGrabber::OutputAudio (ULWord * pInOutBuffer, const ULWord inNumValidBytes)
939 {
940  const ULWord nBytesPerAJASample (4); // AJA devices provide four bytes per channel per sample
941  unsigned channel (0); // Current channel being processed
942  UWord qtSampleNdx (0); // Which Qt audio sample is being processed
943  const ULWord totalSamples (inNumValidBytes / mNumAudioChannels); // Total number of audio samples to process, regardless of channel count
944  const ULWord totalAjaSamples (inNumValidBytes / nBytesPerAJASample); // Total number of AJA-device-provided audio samples, one sample per channel
945  UWord * pQtAudioBuffer (reinterpret_cast<UWord*>(pInOutBuffer)); // Qt-centric pointer to the audio buffer (2-bytes per channel per sample)
946 
947  //
948  // Walk through the audio buffer channel by channel:
949  // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0 1 2 3 4 5 ...etc...
950  // and copy samples from channels 0 and 1 up to the front of the buffer...
951  // 0 1 0 1 0 1 0 1 0 1 0 1 ...etc..
952  //
953  for (unsigned ajaSampleNdx(0); ajaSampleNdx < totalAjaSamples; ajaSampleNdx++)
954  {
955  if (channel < 2)
956  {
957  pQtAudioBuffer [qtSampleNdx] = pInOutBuffer [ajaSampleNdx] >> 16; // Also discard the least significant 16 bits of each sample
958  qtSampleNdx++;
959  } // if channel 0 or 1
960 
961  channel++;
962  if (channel == mNumAudioChannels)
963  channel = 0;
964  } // for each channel for each sample
965 
966  if (mAudioDevice)
967  mAudioDevice->write (reinterpret_cast<const char*>(pQtAudioBuffer), totalSamples);
968 
969 } // OutputAudio
970 
971 
972 #if defined (INCLUDE_AJACC)
973  void NTV2FrameGrabber::Caption608Changed (void * pInstance, const NTV2Caption608ChangeInfo & inChangeInfo)
974  {
975  NTV2FrameGrabber * pFG (reinterpret_cast <NTV2FrameGrabber *> (pInstance));
976  if (pFG)
977  pFG->caption608Changed (inChangeInfo);
978  }
979 
980  void NTV2FrameGrabber::caption608Changed (const NTV2Caption608ChangeInfo & inChangeInfo)
981  {
982  NTV2Line21Attributes attrs;
983  bool changed (false);
984  for (UWord row (NTV2_CC608_MinRow); row <= NTV2_CC608_MaxRow; row++)
985  for (UWord col (NTV2_CC608_MinCol); col <= NTV2_CC608_MaxCol; col++)
986  {
987  ushort utf16Char (m608Decoder ? m608Decoder->GetOnAirUTF16CharacterWithAttributes (row, col, attrs) : 0x0020);
988  if (!utf16Char)
989  utf16Char = 0x0020;
990  if (utf16Char != mScreenBuffer [row-1][col-1])
991  {
992  mScreenBuffer [row-1][col-1] = utf16Char;
993  changed = true;
994  }
995  }
996  if (changed)
997  emit captionScreenChanged (&mScreenBuffer[0][0]);
998  }
999 #endif // defined (INCLUDE_AJACC)
NTV2Channel NTV2InputSourceToChannel(const NTV2InputSource inInputSource)
Converts a given NTV2InputSource to its equivalent NTV2Channel value.
Definition: ntv2utils.cpp:5047
This class handles "analog" (Line 21) based CEA-608 caption data packets.
virtual bool ReleaseStreamForApplicationWithReference(ULWord inApplicationType, int32_t inProcessID)
A reference-counted version of CNTV2DriverInterface::ReleaseStreamForApplication useful for process g...
The invalid video input.
Definition: ntv2enums.h:1277
const UWord NTV2_CC608_MinCol(1)
The minimum column index number (located at the left edge of the screen).
void SetRP188(ULWord ulFrms, ULWord ulSecs, ULWord ulMins, ULWord ulHrs, NTV2FrameRate frameRate, const bool bDropFrame=false, const bool bSMPTE372=false)
Definition: ntv2rp188.cpp:587
#define AJA_SUCCESS(_status_)
Definition: types.h:372
virtual bool SetTaskMode(const NTV2TaskMode inMode)
Sets the device&#39;s task mode.
UByte f2_char1
Caption Byte 1 of Field 2.
virtual void run(void)
My thread function.
virtual AJAStatus AddReceivedAncillaryData(const NTV2Buffer &inReceivedData, const uint32_t inFrameNum=0)
Parse "raw" ancillary data bytes received from hardware (ingest) – see SDI Anc Buffer Data Format –...
Identifies the 5th SDI video input.
Definition: ntv2enums.h:1273
virtual bool GetSDITransmitEnable(const NTV2Channel inChannel, bool &outEnabled)
Answers whether or not the specified SDI connector is currently acting as a transmitter (i...
virtual bool SetHDMIV2Mode(const NTV2HDMIV2Mode inMode)
Sets HDMI V2 mode for the device.
Definition: ntv2hdmi.cpp:678
The AutoCirculate channel is running.
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...
Identifies SMPTE HD 1080p.
Definition: ntv2enums.h:171
This class is used to respond to dynamic events that occur during CEA-608 caption decoding...
UByte f1_char2
Caption Byte 2 of Field 1.
Specifies the device&#39;s internal clock.
Definition: ntv2enums.h:1459
virtual bool SetReference(const NTV2ReferenceSource inRefSource, const bool inKeepFramePulseSelect=(0))
Sets the device&#39;s clock reference source. See Video Output Clocking & Synchronization for more inform...
NTV2TimecodeIndex NTV2InputSourceToTimecodeIndex(const NTV2InputSource inInputSource, const bool inEmbeddedLTC=false)
Converts a given NTV2InputSource to its equivalent NTV2TimecodeIndex value.
Definition: ntv2utils.cpp:5095
This identifies the invalid (unspecified, uninitialized) VANC mode.
Definition: ntv2enums.h:3802
bool IsNULL(void) const
virtual bool SetVideoFormat(const NTV2VideoFormat inVideoFormat, const bool inIsAJARetail=(!(0)), const bool inKeepVancSettings=(0), const NTV2Channel inChannel=NTV2_CHANNEL1)
Configures the AJA device to handle a specific video format.
virtual bool Set4kSquaresEnable(const bool inIsEnabled, const NTV2Channel inChannel)
Enables or disables SMPTE 425 "2K quadrants" mode for the given FrameStore bank on the device...
Obtain audio samples from the device HDMI input, if available.
Definition: ntv2enums.h:2010
UByte f1_char1
Caption Byte 1 of Field 1.
virtual bool IsDeviceReady(const bool inCheckValid=(0))
enum _NTV2VideoFormat NTV2VideoFormat
Identifies a particular video format.
ULWord width(void) const
Declares the AJAAncillaryData_Cea608_line21 class.
static uint64_t GetPid()
Definition: process.cpp:35
Header file for the NTV2FrameGrabber class.
NTV2EmbeddedAudioInput NTV2InputSourceToEmbeddedAudioInput(const NTV2InputSource inInputSource)
Converts a given NTV2InputSource to its equivalent NTV2EmbeddedAudioInput value.
Definition: ntv2utils.cpp:4877
ULWord GetByteCount(void) const
Capture (input) mode, which writes into device SDRAM.
Definition: ntv2enums.h:1243
UByte f2_char2
Caption Byte 2 of Field 2.
virtual bool Close(void)
Closes me, releasing host resources that may have been allocated in a previous Open call...
#define NTV2_IS_4K_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:783
virtual bool GetSDIInput3GbPresent(bool &outValue, const NTV2Channel channel)
virtual bool Open(const UWord inDeviceIndex)
Opens a local/physical AJA device so it can be monitored/controlled.
Obtain audio samples from the audio that&#39;s embedded in the video HANC.
Definition: ntv2enums.h:2007
FRAME_STAMP acFrameStamp
Frame stamp for the transferred frame.
void SetInputSource(const NTV2InputSource inInputSource)
Sets the input to be used for capture on the AJA device being used.
bool CanDoHDMIQuadRasterConversion(void)
void SetTimeCodeSource(const NTV2TCIndex inTCSource)
Definition: json.hpp:5362
virtual bool SetAudioRate(const NTV2AudioRate inRate, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Sets the NTV2AudioRate for the given Audio System.
Definition: ntv2audio.cpp:205
#define false
void ClearCaptionBuffer(const bool inSignalClients=(0))
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.
virtual bool SetFrameBufferFormat(NTV2Channel inChannel, NTV2FrameBufferFormat inNewFormat, bool inIsAJARetail=(!(0)), NTV2HDRXferChars inXferChars=NTV2_VPID_TC_SDR_TV, NTV2HDRColorimetry inColorimetry=NTV2_VPID_Color_Rec709, NTV2HDRLuminance inLuminance=NTV2_VPID_Luminance_YCbCr)
Sets the frame buffer format for the given FrameStore on the AJA device.
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They&#39;re also commonly use...
Definition: ntv2enums.h:1357
virtual class DeviceCapabilities & features(void)
Definition: ntv2card.h:148
virtual bool SetMultiFormatMode(const bool inEnable)
Enables or disables multi-format (per channel) device operation. If enabled, each device channel can ...
virtual bool GetHDMIInputColor(NTV2LHIHDMIColorSpace &outValue, const NTV2Channel inHDMIInput=NTV2_CHANNEL1)
Answers with the current colorspace for the given HDMI input.
Definition: ntv2hdmi.cpp:70
virtual bool GetSDIInput12GPresent(bool &outValue, const NTV2Channel channel)
#define QTPREVIEW_WIDGET_Y
bool IsProgressivePicture(const NTV2VideoFormat format)
Definition: ntv2utils.cpp:5391
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:476
bool GetInputTimeCodes(NTV2TimeCodeList &outValues) const
Returns all RP188 timecodes associated with the frame in NTV2TCIndex order.
Obtain audio samples from the device analog input(s), if available.
Definition: ntv2enums.h:2009
ULWord height(void) const
#define NTV2_AUDIOSIZE_MAX
static QMutex gMutex
NTV2TCIndex
These enum values are indexes into the capture/playout AutoCirculate timecode arrays.
Definition: ntv2enums.h:3951
virtual bool GetTaskMode(NTV2TaskMode &outMode)
Retrieves the device&#39;s current task mode.
virtual bool SetAudioSystemInputSource(const NTV2AudioSystem inAudioSystem, const NTV2AudioSource inAudioSource, const NTV2EmbeddedAudioInput inEmbeddedInput)
Sets the audio source for the given NTV2AudioSystem on the device.
Definition: ntv2audio.cpp:485
AutoCirculate Frame Range.
Definition: ntv2utils.h:971
std::string NTV2InputSourceToString(const NTV2InputSource inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:7377
NTV2OutputXptID GetInputSourceOutputXpt(const NTV2InputSource inInputSource, const bool inIsSDI_DS2=false, const bool inIsHDMI_RGB=false, const UWord inHDMI_Quadrant=0)
static bool Create(CNTV2CaptionDecoder708Ptr &outDecoder)
Creates a new CNTV2CaptionEncoder708 instance.
#define FGNOTE(_expr_)
virtual bool SetLTCInputEnable(const bool inEnable)
Enables or disables the ability for the device to read analog LTC on the reference input connector...
bool IsInput3Gb(const NTV2InputSource inputSource)
#define true
NTV2Standard
Identifies a particular video standard.
Definition: ntv2enums.h:165
Playout (output) mode, which reads from device SDRAM.
Definition: ntv2enums.h:1241
#define NTV2_NUM_IMAGES
virtual std::string GetDescription(void) const
Definition: ntv2card.cpp:139
virtual bool SetMode(const NTV2Channel inChannel, const NTV2Mode inNewValue, const bool inIsRetail=(!(0)))
Determines if a given FrameStore on the AJA device will be used to capture or playout video...
UWord GetDeviceIndex(void) const
virtual bool IsOpen(void) const
#define FGDBG(_expr_)
ULWord GetRasterHeight(const bool inVisibleOnly=false) const
#define AJAAncillaryDataType_Cea608_Vanc
Invalid or "not found".
Definition: ntv2enums.h:98
bool bGotField2Data
True if Field 2 bytes have been set; otherwise false.
virtual bool SetSDITransmitEnable(const NTV2Channel inChannel, const bool inEnable)
Sets the specified bidirectional SDI connector to act as an input or an output.
#define NTV2_INPUT_SOURCE_IS_HDMI(_inpSrc_)
Definition: ntv2enums.h:1281
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 ...
virtual bool SetRP188SourceFilter(const NTV2Channel inSDIInput, const UWord inFilterValue)
Sets the RP188 DBB filter for the given SDI input.
CEA-608 Character Attributes.
#define NTV2_IS_HD_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:737
#define AJA_NULL
Definition: ajatypes.h:167
virtual bool GetVANCMode(NTV2VANCMode &outVancMode, const NTV2Channel inChannel=NTV2_CHANNEL1)
Retrieves the current VANC mode for the given FrameStore.
virtual std::string GetDisplayName(void)
Answers with this device&#39;s display name.
Definition: ntv2card.cpp:88
virtual AJAAncillaryData * GetAncillaryDataWithType(const AJAAncDataType inMatchType, const uint32_t inIndex=0) const
Answers with the AJAAncillaryData object having the given type and index.
static bool Create(CNTV2CaptionDecoder608Ptr &outEncoder)
Creates a new CNTV2CaptionEncoder608 instance.
NTV2InputXptID GetCSCInputXptFromChannel(const NTV2Channel inCSC, const bool inIsKeyInput=false)
NTV2AutoCirculateState acState
Current AutoCirculate state.
virtual NTV2VideoFormat GetInputVideoFormat(const NTV2InputSource inVideoSource=NTV2_INPUTSOURCE_SDI1, const bool inIsProgressive=(0))
Returns the video format of the signal that is present on the given input source. ...
Describes a video frame for a given video standard or format and pixel format, including the total nu...
static void Sleep(const int32_t inMilliseconds)
Suspends execution of the current thread for a given number of milliseconds.
Definition: systemtime.cpp:284
const UWord NTV2_CC608_MaxCol(32)
The maximum column index number (located at the right edge of the screen).
2: OEM (recommended): device configured by client application(s) with some driver involvement...
bool bGotField1Data
True if Field 1 bytes have been set; otherwise false.
NTV2InputXptID GetFrameStoreInputXptFromChannel(const NTV2Channel inFrameStore, const bool inIsBInput=false)
ULWord acAudioTransferSize
Number of bytes captured into the audio buffer.
NTV2InputSource GetNTV2InputSourceForIndex(const ULWord inIndex0, const NTV2IOKinds inKinds=NTV2_IOKINDS_SDI)
Definition: ntv2utils.cpp:5224
ULWord GetIndexForNTV2InputSource(const NTV2InputSource inValue)
Definition: ntv2utils.cpp:5274
std::string NTV2VideoFormatToString(const NTV2VideoFormat inValue, const bool inUseFrameRate=false)
Definition: ntv2utils.cpp:6746
See 8-Bit ARGB, RGBA, ABGR Formats.
Definition: ntv2enums.h:224
virtual bool AcquireStreamForApplicationWithReference(ULWord inApplicationType, int32_t inProcessID)
A reference-counted version of CNTV2DriverInterface::AcquireStreamForApplication useful for process g...
void SetDeviceIndex(const UWord inDeviceIndex)
Sets the AJA device to be used for capture.
virtual bool SetTsiFrameEnable(const bool inIsEnabled, const NTV2Channel inChannel)
Enables or disables SMPTE 425 two-sample interleave (Tsi) frame mode on the device.
NTV2VideoFormat GetVideoFormatFromInputSource(void)
#define AUTOCIRCULATE_WITH_ANC
Use this to AutoCirculate with ancillary data.
Specifies channel or FrameStore 2 (or the 2nd item).
Definition: ntv2enums.h:1360
virtual NTV2DeviceID GetDeviceID(void)
virtual bool GetSDIInput6GPresent(bool &outValue, const NTV2Channel channel)
void GrabCaptions(void)
Performs caption data extraction & decoding.
const UWord NTV2_CC608_MinRow(1)
The minimum row index number (located at the top of the screen).
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
void newFrame(const QImage &inImage, const bool inClear)
This is signaled (called) when a new frame has been captured and is available for display...
virtual bool Connect(const NTV2InputCrosspointID inInputXpt, const NTV2OutputCrosspointID inOutputXpt, const bool inValidate=(0))
Connects the given widget signal input (sink) to the given widget signal output (source).
NTV2InputSource
Identifies a specific video input source.
Definition: ntv2enums.h:1262
A QThread that captures audio/video from NTV2-compatible AJA devices and uses Qt signals to emit ARGB...
bool CheckForValidInput(void)
#define IsValidLine21Channel(_chan_)
virtual bool SetAudioBufferSize(const NTV2AudioBufferSize inValue, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Changes the size of the audio buffer that is used for a given Audio System in the AJA device...
Definition: ntv2audio.cpp:249
virtual uint32_t CountAncillaryDataWithType(const AJAAncDataType inMatchType) const
Answers with the number of AJAAncillaryData objects having the given type.
bool SetupInput(void)
Configures my AJA device for capture.
#define DEC(__x__)
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.
This identifies the first Audio System.
Definition: ntv2enums.h:3897
void SetupAudio(void)
Performs audio configuration.
NTV2LHIHDMIColorSpace GetColorSpaceFromInputSource(void)
#define NTV2_IS_VALID_INPUT_SOURCE(_inpSrc_)
Definition: ntv2enums.h:1284
static const ULWord kDemoAppSignature((((uint32_t)( 'D'))<< 24)|(((uint32_t)( 'E'))<< 16)|(((uint32_t)( 'M'))<< 8)|(((uint32_t)( 'O'))<< 0))
Declares numerous NTV2 utility functions.
ULWord acBufferLevel
Number of buffered frames in driver ready to capture or play.
This structure encapsulates all possible CEA-608 caption data bytes that may be associated with a giv...
static bool Get4KInputFormat(NTV2VideoFormat &inOutVideoFormat)
Given a video format, if all 4 inputs are the same and promotable to 4K, this function does the promo...
Specifies the Analog In 1 connector.
Definition: ntv2enums.h:1460
virtual AJAStatus ParseAllAncillaryData(void)
Sends a "ParsePayloadData" command to all of my AJAAncillaryData objects.
This is returned from the CNTV2Card::AutoCirculateGetStatus function.
std::vector< NTV2_RP188 > NTV2TimeCodeList
An ordered sequence of zero or more NTV2_RP188 structures. An NTV2TCIndex enum value can be used as a...
void StopAutoCirculate(void)
Stops capturing.
uint16_t UWord
Definition: ajatypes.h:221
ULWord GetRasterWidth(void) const
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1359
virtual bool AutoCirculateStart(const NTV2Channel inChannel, const ULWord64 inStartTime=0)
Starts AutoCirculating the specified channel that was previously initialized by CNTV2Card::AutoCircul...
void captionScreenChanged(const ushort *pInScreen)
This is signaled (called) when my caption screen buffer changes.
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.
void newStatusString(const QString &inStatus)
This is signaled (called) when my status string changes.
NTV2VANCMode
These enum values identify the available VANC modes.
Definition: ntv2enums.h:3797
virtual bool SetSDIInLevelBtoLevelAConversion(const NTV2ChannelSet &inSDIInputs, const bool inEnable)
Enables or disables 3G level B to 3G level A conversion at the SDI input(s).
#define NTV2_INPUT_SOURCE_IS_ANALOG(_inpSrc_)
Definition: ntv2enums.h:1282
NTV2AudioSource
This enum value determines/states where an audio system will obtain its audio samples.
Definition: ntv2enums.h:2005
NTV2AudioSystem NTV2ChannelToAudioSystem(const NTV2Channel inChannel)
Converts the given NTV2Channel value into its equivalent NTV2AudioSystem.
Definition: ntv2utils.cpp:4869
NTV2FrameGrabber(QObject *pInParentObject=NULL)
Constructs me.
Specifies channel or FrameStore 4 (or the 4th item).
Definition: ntv2enums.h:1362
This file contains some structures, constants, classes and functions that are used in some of the dem...
Specifies channel or FrameStore 5 (or the 5th item).
Definition: ntv2enums.h:1363
Identifies the first analog video input.
Definition: ntv2enums.h:1264
NTV2Standard GetNTV2StandardFromVideoFormat(const NTV2VideoFormat inVideoFormat)
Definition: ntv2utils.cpp:2375
#define NTV2_IS_VALID_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:725
void * GetHostPointer(void) const
#define AJAAncillaryDataType_Cea708
NTV2OutputXptID GetSDIInputOutputXptFromChannel(const NTV2Channel inSDIInput, const bool inIsDS2=false)
#define QTPREVIEW_WIDGET_X
const UWord NTV2_CC608_MaxRow(15)
The maximum permissible row index number (located at the bottom of the screen).
NTV2Buffer acAudioBuffer
The host audio buffer. This field is owned by the client application, and thus is responsible for all...
I am the principal class that stores a single SMPTE-291 SDI ancillary data packet OR the digitized co...
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.
#define NTV2_INPUT_SOURCE_IS_SDI(_inpSrc_)
Definition: ntv2enums.h:1283
Declares the AJAAncillaryList class.
NTV2FrameSize & set(const ULWord inWidth, const ULWord inHeight)
Sets my dimension values.
NTV2Line21Channel
The CEA-608 caption channels: CC1 thru CC4, TX1 thru TX4, plus XDS.
#define AJAAncillaryDataType_Cea608_Line21
#define FGWARN(_expr_)
virtual bool GetTsiFrameEnable(bool &outIsEnabled, const NTV2Channel inChannel)
Returns the current SMPTE 425 two-sample-interleave frame mode on the device, whether it&#39;s enabled or...
NTV2Buffer acANCBuffer
The host ancillary data buffer. This field is owned by the client application, and thus is responsibl...
Identifies the 1st SDI video input.
Definition: ntv2enums.h:1269
virtual bool SetNumberAudioChannels(const ULWord inNumChannels, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Sets the number of audio channels to be concurrently captured or played for a given Audio System on t...
Definition: ntv2audio.cpp:146
void OutputAudio(ULWord *pInOutAudioBuffer, const ULWord inNumValidBytes)
Writes audio samples for channels 1 and 2 that are in the given audio buffer to my QAudioOutput devic...
NTV2OutputXptID GetCSCOutputXptFromChannel(const NTV2Channel inCSC, const bool inIsKey=false, const bool inIsRGB=false)
virtual bool WaitForInputVerticalInterrupt(const NTV2Channel inChannel=NTV2_CHANNEL1, UWord inRepeatCount=1)
Efficiently sleeps the calling thread/process until the next one or more field (interlaced video) or ...
I am an ordered collection of AJAAncillaryData instances which represent one or more SMPTE 291 data p...
Definition: ancillarylist.h:64
virtual ~NTV2FrameGrabber()
My destructor.
#define NTV2_ANCSIZE_MAX
bool SetVideoBuffer(ULWord *pInVideoBuffer, const ULWord inVideoByteCount)
Sets my video buffer for use in a subsequent call to CNTV2Card::AutoCirculateTransfer.
Specifies channel or FrameStore 3 (or the 3rd item).
Definition: ntv2enums.h:1361
NTV2LHIHDMIColorSpace
Definition: ntv2enums.h:3678
NTV2ReferenceSource NTV2InputSourceToReferenceSource(const NTV2InputSource inInputSource)
Converts a given NTV2InputSource to its equivalent NTV2ReferenceSource value.
Definition: ntv2utils.cpp:5023
virtual bool EnableChannel(const NTV2Channel inChannel)
Enables the given FrameStore.