AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
ntv2player.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2player.h"
9 #include "ntv2debug.h"
10 #include "ntv2devicescanner.h"
11 #include "ntv2audiodefines.h"
12 #include "ntv2testpatterngen.h"
14 #include "ajabase/system/process.h"
15 #include "ajabase/system/file_io.h"
16 #include <fstream> // For ifstream
17 
18 using namespace std;
19 
20 //#define NTV2_BUFFER_LOCKING // Define this to pre-lock video/audio buffers in kernel
21 
22 // Convenience macros for EZ logging:
23 #define TCFAIL(_expr_) AJA_sERROR (AJA_DebugUnit_TimecodeGeneric, AJAFUNC << ": " << _expr_)
24 #define TCWARN(_expr_) AJA_sWARNING(AJA_DebugUnit_TimecodeGeneric, AJAFUNC << ": " << _expr_)
25 #define TCNOTE(_expr_) AJA_sNOTICE (AJA_DebugUnit_TimecodeGeneric, AJAFUNC << ": " << _expr_)
26 #define TCINFO(_expr_) AJA_sINFO (AJA_DebugUnit_TimecodeGeneric, AJAFUNC << ": " << _expr_)
27 #define TCDBG(_expr_) AJA_sDEBUG (AJA_DebugUnit_TimecodeGeneric, AJAFUNC << ": " << _expr_)
28 
34 static ULWord gAncMaxSizeBytes (NTV2_ANCSIZE_MAX); // Max per-frame anc buffer size, in bytes
35 
44 static const uint32_t gAudMaxSizeBytes (256 * 1024); // Max per-frame audio buffer size, in bytes
45 
46 static const bool BUFFER_PAGE_ALIGNED (true);
47 
48 // Audio tone generator data
49 static const double gFrequencies [] = {250.0, 500.0, 1000.0, 2000.0};
50 static const ULWord gNumFrequencies (sizeof(gFrequencies) / sizeof(double));
51 static const double gAmplitudes [] = { 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85,
52  0.85, 0.80, 0.75, 0.70, 0.65, 0.60, 0.55, 0.50, 0.45, 0.40, 0.35, 0.30, 0.25, 0.20, 0.15, 0.10};
53 
54 
56  : mConfig (inConfig),
57  mConsumerThread (),
58  mProducerThread (),
59  mDevice (),
60  mSavedTaskMode (NTV2_TASK_MODE_INVALID),
61  mCurrentFrame (0),
62  mCurrentSample (0),
63  mToneFrequency (440.0),
64  mAudioSystem (NTV2_AUDIOSYSTEM_INVALID),
65  mFormatDesc (),
66  mTCIndexes (),
67  mGlobalQuit (false),
68  mTCBurner (),
69  mHostBuffers (),
70  mFrameDataRing (),
71  mTestPatRasters ()
72 {
73 }
74 
75 
77 {
78  // Stop my playout and producer threads, then destroy them...
79  Quit();
80 
81  mDevice.UnsubscribeOutputVerticalEvent(mConfig.fOutputChannel); // Unsubscribe from output VBI event
82 } // destructor
83 
84 
85 void NTV2Player::Quit (void)
86 {
87  // Set the global 'quit' flag, and wait for the threads to go inactive...
88  mGlobalQuit = true;
89 
90  while (mProducerThread.Active())
91  AJATime::Sleep(10);
92 
93  while (mConsumerThread.Active())
94  AJATime::Sleep(10);
95 
96 #if defined(NTV2_BUFFER_LOCKING)
97  mDevice.DMABufferUnlockAll();
98 #endif // NTV2_BUFFER_LOCKING
99  if (!mConfig.fDoMultiFormat && mDevice.IsOpen())
100  {
102  if (NTV2_IS_VALID_TASK_MODE(mSavedTaskMode))
103  mDevice.SetTaskMode(mSavedTaskMode); // Restore prior task mode
104  }
105 } // Quit
106 
107 
109 {
110  AJAStatus status (AJA_STATUS_SUCCESS);
111 
112  // Open the device...
114  {cerr << "## ERROR: Device '" << mConfig.fDeviceSpec << "' not found" << endl; return AJA_STATUS_OPEN;}
115 
116  if (!mDevice.IsDeviceReady(false))
117  {cerr << "## ERROR: Device '" << mDevice.GetDisplayName() << "' not ready" << endl; return AJA_STATUS_INITIALIZE;}
118  if (!mDevice.features().CanDoPlayback())
119  {cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' is capture-only" << endl; return AJA_STATUS_FEATURE;}
120 
121  const UWord maxNumChannels (mDevice.features().GetNumFrameStores());
122 
123  // Beware -- some older devices (e.g. Corvid1) can only output from FrameStore 2...
124  if ((mConfig.fOutputChannel == NTV2_CHANNEL1) && (!mDevice.features().CanDoFrameStore1Display()))
125  mConfig.fOutputChannel = NTV2_CHANNEL2;
126  if (UWord(mConfig.fOutputChannel) >= maxNumChannels)
127  {
128  cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' can't use Ch" << DEC(mConfig.fOutputChannel+1)
129  << " -- only supports Ch1" << (maxNumChannels > 1 ? string("-Ch") + string(1, char(maxNumChannels+'0')) : "") << endl;
130  return AJA_STATUS_UNSUPPORTED;
131  }
132 
133  if (!mConfig.fAncDataFilePath.empty())
135  {
136  cerr << "## ERROR: Anc data file '" << mConfig.fAncDataFilePath << "' not found" << endl;
137  return AJA_STATUS_NOT_FOUND;
138  }
139 
140  if (!mConfig.fDoMultiFormat)
141  {
142  mDevice.GetTaskMode(mSavedTaskMode); // Save the current task mode
144  return AJA_STATUS_BUSY; // Device is in use by another app -- fail
145  }
146  mDevice.SetTaskMode(NTV2_OEM_TASKS); // Set OEM service level
147 
148  if (mDevice.features().CanDoMultiFormat())
149  mDevice.SetMultiFormatMode(mConfig.fDoMultiFormat);
150  else
151  mConfig.fDoMultiFormat = false;
152 
153  // Set up the video and audio...
154  status = SetUpVideo();
155  if (AJA_FAILURE(status))
156  return status;
157  status = mConfig.WithAudio() ? SetUpAudio() : AJA_STATUS_SUCCESS;
158  if (AJA_FAILURE(status))
159  return status;
160 
161  // Set up the circular buffers, and the test pattern buffers...
162  status = SetUpHostBuffers();
163  if (AJA_FAILURE(status))
164  return status;
165  status = SetUpTestPatternBuffers();
166  if (AJA_FAILURE(status))
167  return status;
168 
169  // Set up the device signal routing...
170  if (!RouteOutputSignal())
171  return AJA_STATUS_FAIL;
172 
173  // Lastly, prepare my AJATimeCodeBurn instance...
174  if (!mTCBurner.RenderTimeCodeFont (CNTV2DemoCommon::GetAJAPixelFormat(mConfig.fPixelFormat), mFormatDesc.numPixels, mFormatDesc.numLines))
175  {cerr << "## ERROR: RenderTimeCodeFont failed for: " << mFormatDesc << endl; return AJA_STATUS_UNSUPPORTED;}
176 
177  // Ready to go...
178  #if defined(_DEBUG)
179  cerr << mConfig;
180  if (mDevice.IsRemote())
181  cerr << "Device Description: " << mDevice.GetDescription() << endl;
182  cerr << endl;
183  #endif // defined(_DEBUG)
184  return AJA_STATUS_SUCCESS;
185 
186 } // Init
187 
188 
190 {
191  // Configure the device to output the requested video format...
192  if (mConfig.fVideoFormat == NTV2_FORMAT_UNKNOWN)
193  return AJA_STATUS_BAD_PARAM;
194  if (!mDevice.features().CanDoVideoFormat(mConfig.fVideoFormat))
195  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' doesn't support "
196  << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << endl;
197  return AJA_STATUS_UNSUPPORTED;
198  }
199  if (!mDevice.features().CanDoFrameBufferFormat(mConfig.fPixelFormat))
200  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' doesn't support "
201  << ::NTV2FrameBufferFormatString(mConfig.fPixelFormat) << endl;
202  return AJA_STATUS_UNSUPPORTED;
203  }
204 
205  // This demo doesn't playout dual-link RGB over SDI -- only YCbCr.
206  // Check that this device has a CSC to convert RGB to YUV...
207  if (::IsRGBFormat(mConfig.fPixelFormat)) // If RGB FBF...
208  if (UWord(mConfig.fOutputChannel) > mDevice.features().GetNumCSCs()) // No CSC for this channel?
209  {cerr << "## ERROR: No CSC for channel " << DEC(mConfig.fOutputChannel+1) << " to convert RGB pixel format" << endl;
210  return AJA_STATUS_UNSUPPORTED;}
211 
212  if (!mDevice.features().CanDo3GLevelConversion() && mConfig.fDoABConversion && ::IsVideoFormatA(mConfig.fVideoFormat))
213  mConfig.fDoABConversion = false;
214  if (mConfig.fDoABConversion)
216 
217  // Keep the raster description handy...
218  mFormatDesc = NTV2FormatDescriptor(mConfig.fVideoFormat, mConfig.fPixelFormat);
219  if (!mFormatDesc.IsValid())
220  return AJA_STATUS_FAIL;
221 
222  // If we own the whole device, make sure all FrameStores are disabled (good practice)
223  if (!mConfig.fDoMultiFormat)
224  {
225  NTV2ChannelSet enabledChannels;
226  mDevice.GetEnabledChannels(enabledChannels);
227  mDevice.DisableChannels(enabledChannels);
228  }
229 
230  // Turn on the FrameStore (to read frame buffer memory and transmit video)...
231  mDevice.EnableChannel(mConfig.fOutputChannel);
232 
233  // This demo assumes VANC is disabled...
234  mDevice.SetVANCMode(NTV2_VANCMODE_OFF, mConfig.fOutputChannel);
236 
237  // Set the FrameStore video format...
238  mDevice.SetVideoFormat (mConfig.fVideoFormat, false, false, mConfig.fOutputChannel);
239 
240  // Set the frame buffer pixel format for the device FrameStore...
241  mDevice.SetFrameBufferFormat (mConfig.fOutputChannel, mConfig.fPixelFormat);
242 
243  // The output interrupt is Enabled by default, but on some platforms, you must subscribe to it
244  // in order to be able to wait on its event/semaphore...
246 
247  // Get current per-field maximum Anc buffer size...
250 
251  // Set output clock reference...
253 
254  // At this point, video setup is complete (except for widget signal routing).
255  return AJA_STATUS_SUCCESS;
256 
257 } // SetUpVideo
258 
259 
261 {
262  uint16_t numAudioChannels (mDevice.features().GetMaxAudioChannels());
263  if (numAudioChannels > 8) // If audio system handles more than 8 channels...
264  if (!mDevice.features().CanDo2110()) // ...and SDI (i.e. not ST 2110 IP streaming)...
265  if (NTV2_IS_2K_1080_VIDEO_FORMAT(mConfig.fVideoFormat)) // ...and 2K (narrower HANC only fits 8 audio channels)
266  numAudioChannels = 8; // ...then reduce to 8 audio channels
267 
268  mAudioSystem = NTV2_AUDIOSYSTEM_1; // Use NTV2_AUDIOSYSTEM_1...
269  if (mDevice.features().GetNumAudioSystems() > 1) // ...but if the device has more than one audio system...
270  mAudioSystem = ::NTV2ChannelToAudioSystem(mConfig.fOutputChannel); // ...base it on the channel
271  // However, there are a few older devices that have only 1 audio system,
272  // yet 2 frame stores (or must use channel 2 for playout)...
273  if (!mDevice.features().CanDoFrameStore1Display())
274  mAudioSystem = NTV2_AUDIOSYSTEM_1;
275 
276  mDevice.SetNumberAudioChannels (numAudioChannels, mAudioSystem);
277  mDevice.SetAudioRate (NTV2_AUDIO_48K, mAudioSystem);
278 
279  // How big should the on-device audio buffer be? 1MB? 2MB? 4MB? 8MB?
280  // For this demo, 4MB will work best across all platforms (Windows, Mac & Linux)...
281  mDevice.SetAudioBufferSize (NTV2_AUDIO_BUFFER_BIG, mAudioSystem);
282 
283  // Set the SDI output audio embedders to embed audio samples from the output of mAudioSystem...
284  mDevice.SetSDIOutputAudioSystem (mConfig.fOutputChannel, mAudioSystem);
285  mDevice.SetSDIOutputDS2AudioSystem (mConfig.fOutputChannel, mAudioSystem);
286 
287  // If the last app using the device left it in E-E mode (input passthru), then loopback
288  // must be disabled --- otherwise the output audio will be pass-thru SDI input audio...
289  mDevice.SetAudioLoopBack (NTV2_AUDIO_LOOPBACK_OFF, mAudioSystem);
290 
291  if (!mConfig.fDoMultiFormat && mDevice.features().GetNumHDMIVideoOutputs())
292  {
296  }
297 
298  return AJA_STATUS_SUCCESS;
299 
300 } // SetUpAudio
301 
302 
304 {
305  CNTV2DemoCommon::SetDefaultPageSize(); // Set host-specific page size
306 
307  // Let my circular buffer know when it's time to quit...
308  mFrameDataRing.SetAbortFlag (&mGlobalQuit);
309 
310  // Allocate and add each in-host NTV2FrameData to my circular buffer member variable...
311  mHostBuffers.reserve(CIRCULAR_BUFFER_SIZE);
312  while (mHostBuffers.size() < CIRCULAR_BUFFER_SIZE)
313  {
314  mHostBuffers.push_back(NTV2FrameData()); // Make a new NTV2FrameData...
315  NTV2FrameData & frameData(mHostBuffers.back()); // ...and get a reference to it
316 
317  // Allocate a page-aligned video buffer
318  if (mConfig.WithVideo())
319  if (!frameData.fVideoBuffer.Allocate (mFormatDesc.GetTotalBytes(), BUFFER_PAGE_ALIGNED))
320  {
321  PLFAIL("Failed to allocate " << xHEX0N(mFormatDesc.GetTotalBytes(),8) << "-byte video buffer");
322  return AJA_STATUS_MEMORY;
323  }
324  #ifdef NTV2_BUFFER_LOCKING
325  if (frameData.fVideoBuffer)
326  mDevice.DMABufferLock(frameData.fVideoBuffer, true);
327  #endif
328 
329  // Allocate a page-aligned audio buffer (if transmitting audio)
330  if (mConfig.WithAudio())
331  if (!frameData.fAudioBuffer.Allocate (gAudMaxSizeBytes, BUFFER_PAGE_ALIGNED))
332  {
333  PLFAIL("Failed to allocate " << xHEX0N(gAudMaxSizeBytes,8) << "-byte audio buffer");
334  return AJA_STATUS_MEMORY;
335  }
336  #ifdef NTV2_BUFFER_LOCKING
337  if (frameData.fAudioBuffer)
338  mDevice.DMABufferLock(frameData.fAudioBuffer, /*alsoPreLockSGL*/true);
339  #endif
340  mFrameDataRing.Add (&frameData);
341  } // for each NTV2FrameData
342 
343  return AJA_STATUS_SUCCESS;
344 
345 } // SetUpHostBuffers
346 
347 
349 {
350  vector<NTV2TestPatternSelect> testPatIDs;
351  testPatIDs.push_back(NTV2_TestPatt_ColorBars100);
352  testPatIDs.push_back(NTV2_TestPatt_ColorBars75);
353  testPatIDs.push_back(NTV2_TestPatt_Ramp);
354  testPatIDs.push_back(NTV2_TestPatt_MultiBurst);
355  testPatIDs.push_back(NTV2_TestPatt_LineSweep);
356  testPatIDs.push_back(NTV2_TestPatt_CheckField);
357  testPatIDs.push_back(NTV2_TestPatt_FlatField);
358  testPatIDs.push_back(NTV2_TestPatt_MultiPattern);
359 
360  mTestPatRasters.clear();
361  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
362  mTestPatRasters.push_back(NTV2Buffer());
363 
364  if (!mFormatDesc.IsValid())
365  {PLFAIL("Bad format descriptor"); return AJA_STATUS_FAIL;}
366  if (mFormatDesc.IsVANC())
367  {PLFAIL("VANC should have been disabled: " << mFormatDesc); return AJA_STATUS_FAIL;}
368 
369  // Set up one video buffer for each test pattern...
370  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
371  {
372  // Allocate the buffer memory...
373  if (!mTestPatRasters.at(tpNdx).Allocate (mFormatDesc.GetTotalBytes(), BUFFER_PAGE_ALIGNED))
374  { PLFAIL("Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << ": "
375  << xHEX0N(mFormatDesc.GetTotalBytes(),8) << "-byte page-aligned alloc failed");
376  return AJA_STATUS_MEMORY;
377  }
378 
379  // Fill the buffer with test pattern...
380  NTV2TestPatternGen testPatternGen;
381  if (!testPatternGen.DrawTestPattern (testPatIDs.at(tpNdx), mFormatDesc, mTestPatRasters.at(tpNdx)))
382  {
383  cerr << "## ERROR: DrawTestPattern " << DEC(tpNdx) << " failed: " << mFormatDesc << endl;
384  return AJA_STATUS_FAIL;
385  }
386 
387  #ifdef NTV2_BUFFER_LOCKING
388  // Try to prelock the memory, including its scatter-gather list...
389  if (!mDevice.DMABufferLock(mTestPatRasters.at(tpNdx), /*alsoLockSegmentMap=*/true))
390  PLWARN("Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << ": failed to pre-lock");
391  #endif
392  } // loop for each predefined pattern
393 
394  return AJA_STATUS_SUCCESS;
395 
396 } // SetUpTestPatternBuffers
397 
398 
400 {
401  const NTV2Standard outputStandard (::GetNTV2StandardFromVideoFormat(mConfig.fVideoFormat));
402  const bool isRGB (::IsRGBFormat(mConfig.fPixelFormat));
403  const bool canVerify (mDevice.features().HasCrosspointConnectROM());
404  UWord connectFailures (0);
405 
406  // Since this function figures out which SDI spigots will be set up for output,
407  // it also sets the "mTCIndexes" member, which determines which timecodes will
408  // be transmitted (and on which SDI spigots)...
409  mTCIndexes.clear();
410 
411  const NTV2OutputXptID cscVidOutXpt(::GetCSCOutputXptFromChannel(mConfig.fOutputChannel, false/*isKey*/, !isRGB/*isRGB*/));
412  const NTV2OutputXptID fsVidOutXpt (::GetFrameStoreOutputXptFromChannel(mConfig.fOutputChannel, isRGB/*isRGB*/, false/*is425*/));
413  const NTV2InputXptID cscInputXpt (isRGB ? ::GetCSCInputXptFromChannel(mConfig.fOutputChannel, false/*isKeyInput*/) : NTV2_INPUT_CROSSPOINT_INVALID);
414 
415  if (!mConfig.fDoMultiFormat) // Not multiformat: We own the whole device...
416  {
417  mDevice.ClearRouting(); // Start with clean slate
418  }
419 
420  if (isRGB)
421  if (!mDevice.Connect (cscInputXpt, fsVidOutXpt, canVerify))
422  connectFailures++;
423 
424  if (mDevice.features().HasBiDirectionalSDI())
425  mDevice.SetSDITransmitEnable(mConfig.fOutputChannel, true);
426 
427  if (!mDevice.Connect (::GetSDIOutputInputXpt (mConfig.fOutputChannel, false/*isDS2*/), isRGB ? cscVidOutXpt : fsVidOutXpt, canVerify))
428  connectFailures++;
429 
430  mDevice.SetSDIOutputStandard (mConfig.fOutputChannel, outputStandard);
431 
432  mTCIndexes.insert (::NTV2ChannelToTimecodeIndex(mConfig.fOutputChannel, /*inEmbeddedLTC=*/mConfig.fTransmitLTC));
433  // NOTE: No need to send VITC2 with VITC1 (for "i" formats) -- firmware does this automatically
434 
435  if (!mConfig.fDoMultiFormat) // Not multiformat: We own the whole device...
436  {
437  // Also connect analog video output, if the device has one...
438  if (mDevice.features().GetNumAnalogVideoOutputs() && mConfig.fOutputChannel == NTV2_CHANNEL1)
439  if (!mDevice.Connect (::GetOutputDestInputXpt(NTV2_OUTPUTDESTINATION_ANALOG1), isRGB ? cscVidOutXpt : fsVidOutXpt, canVerify))
440  connectFailures++;
441 
442  // Also connect HDMI video output, if the device has one...
443  if (mDevice.features().GetNumHDMIVideoOutputs() && mConfig.fOutputChannel == NTV2_CHANNEL1)
444  {
445  if (!mDevice.Connect (::GetOutputDestInputXpt(NTV2_OUTPUTDESTINATION_HDMI1), isRGB ? cscVidOutXpt : fsVidOutXpt, canVerify))
446  connectFailures++;
447  }
448  }
449  TCNOTE(mTCIndexes);
450  if (connectFailures)
451  PLWARN(DEC(connectFailures) << " 'Connect' call(s) failed");
452  return connectFailures == 0;
453 
454 } // RouteOutputSignal
455 
456 
458 {
459  // Start my consumer and producer threads...
462  return AJA_STATUS_SUCCESS;
463 
464 } // Run
465 
466 
467 
469 // This is where the play thread starts
470 
472 {
473  // Create and start the playout thread...
474  mConsumerThread.Attach (ConsumerThreadStatic, this);
475  mConsumerThread.SetPriority(AJA_ThreadPriority_High);
476  mConsumerThread.Start();
477 
478 } // StartConsumerThread
479 
480 
481 // The playout thread function
482 void NTV2Player::ConsumerThreadStatic (AJAThread * pThread, void * pContext) // static
483 { (void) pThread;
484  // Grab the NTV2Player instance pointer from the pContext parameter,
485  // then call its ConsumeFrames method...
486  NTV2Player * pApp (reinterpret_cast<NTV2Player*>(pContext));
487  if (pApp)
488  pApp->ConsumeFrames();
489 
490 } // ConsumerThreadStatic
491 
492 
493 static uint64_t sTotalAncFileBytes(0), sCurrentAncFileBytes(0);
494 
495 
497 {
498  ULWord acOptions (AUTOCIRCULATE_WITH_RP188);
499  AUTOCIRCULATE_TRANSFER outputXfer;
500  AUTOCIRCULATE_STATUS outputStatus;
501  ULWord goodXfers(0), badXfers(0), starves(0), noRoomWaits(0);
502  ifstream * pAncStrm (AJA_NULL);
503 
504  // Stop AutoCirculate, just in case someone else left it running...
505  mDevice.AutoCirculateStop(mConfig.fOutputChannel);
506  mDevice.WaitForOutputVerticalInterrupt(mConfig.fOutputChannel, 4); // Let it stop
507  PLNOTE("Thread started");
508 
509  if (!mConfig.fAncDataFilePath.empty())
510  { // Open raw anc file for reading...
511  pAncStrm = new ifstream(mConfig.fAncDataFilePath.c_str(), ios::binary);
512  do
513  {
514  if (!pAncStrm->good())
515  { PLFAIL("Cannot open anc file '" << mConfig.fAncDataFilePath << "' -- anc insertion disabled");
516  delete pAncStrm; pAncStrm = AJA_NULL;
517  break;
518  }
519  pAncStrm->seekg(0, std::ios_base::end);
520  if (pAncStrm->tellg() == -1)
521  { PLFAIL("Cannot determine anc file size -- anc insertion disabled");
522  delete pAncStrm; pAncStrm = AJA_NULL;
523  break;
524  }
525  sTotalAncFileBytes = uint64_t(pAncStrm->tellg());
526  pAncStrm->seekg(0); // Rewind to start
528  { PLFAIL("anc buffer size " << DEC(gAncMaxSizeBytes*2) << " exceeds anc file size " << DEC(sTotalAncFileBytes)
529  << " -- anc insertion disabled");
530  delete pAncStrm; pAncStrm = AJA_NULL;
531  break;
532  }
533  // Allocate anc buffers...
534  bool ancOK = outputXfer.acANCBuffer.Allocate(gAncMaxSizeBytes, BUFFER_PAGE_ALIGNED);
537  if (!ancOK)
538  {
539  PLFAIL("Anc buffer " << xHEX0N(gAncMaxSizeBytes,8) << "(" << DEC(gAncMaxSizeBytes) << ")-byte"
540  " allocation failed -- anc insertion disabled");
541  outputXfer.acANCBuffer.Deallocate();
542  outputXfer.acANCField2Buffer.Deallocate();
543  delete pAncStrm;
544  pAncStrm = AJA_NULL;
545  break;
546  }
547  acOptions |= AUTOCIRCULATE_WITH_ANC;
548  break; // Good to go!
549  } while (false); // Once thru
550  }
551 #ifdef NTV2_BUFFER_LOCKING
552  if (outputXferInfo.acANCBuffer)
553  mDevice.DMABufferLock(outputXfer.acANCBuffer, /*alsoLockSGL*/true);
554  if (outputXferInfo.acANCField2Buffer)
555  mDevice.DMABufferLock(outputXfer.acANCField2Buffer, /*alsoLockSGL*/true);
556 #endif
557 
558  // Initialize & start AutoCirculate...
559  bool initOK = mDevice.AutoCirculateInitForOutput (mConfig.fOutputChannel, mConfig.fFrames, mAudioSystem, acOptions);
560  if (!initOK)
561  {PLFAIL("AutoCirculateInitForOutput failed"); mGlobalQuit = true;}
562  else if (!mConfig.WithVideo())
563  { // Video suppressed --
564  // Clear device frame buffers being AutoCirculated (prevent garbage output frames)
565  NTV2Buffer tmpFrame (mFormatDesc.GetVideoWriteSize());
566  NTV2TestPatternGen blackPatternGen;
567  blackPatternGen.DrawTestPattern (NTV2_TestPatt_Black, mFormatDesc, tmpFrame);
568  mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outputStatus);
569  for (uint16_t frmNum(outputStatus.GetStartFrame()); frmNum <= outputStatus.GetEndFrame(); frmNum++)
570  mDevice.DMAWriteFrame(ULWord(frmNum), tmpFrame, mFormatDesc.GetTotalBytes());
571  } // else if --novideo
572 
573  while (!mGlobalQuit)
574  {
575  mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outputStatus);
576 
577  // Check if there's room for another frame on the card...
578  if (outputStatus.CanAcceptMoreOutputFrames())
579  {
580  // Device has at least one free frame buffer that can be filled.
581  // Wait for the next frame in our ring to become ready to "consume"...
582  NTV2FrameData * pFrameData (mFrameDataRing.StartConsumeNextBuffer());
583  if (!pFrameData)
584  {starves++; continue;}
585 
586  outputXfer.SetOutputTimeCodes(pFrameData->fTimecodes);
587 
588  if (pFrameData->VideoBuffer()) // Transfer the timecode-burned frame to the device for playout...
589  outputXfer.SetVideoBuffer (pFrameData->VideoBuffer(), pFrameData->VideoBufferSize());
590  if (pFrameData->AudioBuffer()) // If also playing audio...
591  outputXfer.SetAudioBuffer (pFrameData->AudioBuffer(), pFrameData->fNumAudioBytes);
592 
593  if (pAncStrm && pAncStrm->good() && outputXfer.acANCBuffer)
594  { // Read pre-recorded anc from binary data file, and inject it into this frame...
595  pAncStrm->read(outputXfer.acANCBuffer, streamsize(outputXfer.acANCBuffer.GetByteCount()));
596  sCurrentAncFileBytes += pAncStrm->good() ? outputXfer.acANCBuffer.GetByteCount() : 0;
597  if (pAncStrm->good() && outputXfer.acANCField2Buffer)
598  {
599  pAncStrm->read(outputXfer.acANCField2Buffer, streamsize(outputXfer.acANCField2Buffer.GetByteCount()));
600  sCurrentAncFileBytes += pAncStrm->good() ? outputXfer.acANCField2Buffer.GetByteCount() : 0;
601  }
602  if (pAncStrm->eof())
603  { pAncStrm->clear();
604  pAncStrm->seekg(0); // Rewind upon EOF
606  PLDBG("Anc file rewound: " << DEC(goodXfers) << " goodXfers, " << DEC(badXfers) << " badXfers");
607  }
608  } // if playing anc from binary data file
609 
610  // Perform the DMA transfer to the device...
611  if (mDevice.AutoCirculateTransfer (mConfig.fOutputChannel, outputXfer))
612  goodXfers++;
613  else
614  badXfers++;
615 
616  if (goodXfers == 3)
617  mDevice.AutoCirculateStart(mConfig.fOutputChannel);
618 
619  // Signal that the frame has been "consumed"...
620  mFrameDataRing.EndConsumeNextBuffer();
621  continue; // Back to top of while loop
622  } // if CanAcceptMoreOutputFrames
623 
624  // Wait for one or more buffers to become available on the device, which should occur at next VBI...
625  noRoomWaits++;
627  } // loop til quit signaled
628 
629  // Stop AutoCirculate...
630  mDevice.AutoCirculateStop(mConfig.fOutputChannel);
631  PLNOTE("Thread completed: " << DEC(goodXfers) << " xfers, " << DEC(badXfers) << " failed, "
632  << DEC(starves) << " starves, " << DEC(noRoomWaits) << " VBI waits");
633  if (pAncStrm)
634  delete pAncStrm;
635 
636 } // ConsumeFrames
637 
638 
639 
641 // This is where the producer thread starts
642 
644 {
645  // Create and start the producer thread...
646  mProducerThread.Attach(ProducerThreadStatic, this);
647  mProducerThread.SetPriority(AJA_ThreadPriority_High);
648  mProducerThread.Start();
649 
650 } // StartProducerThread
651 
652 
653 void NTV2Player::ProducerThreadStatic (AJAThread * pThread, void * pContext) // static
654 { (void) pThread;
655  NTV2Player * pApp (reinterpret_cast<NTV2Player*>(pContext));
656  if (pApp)
657  pApp->ProduceFrames();
658 
659 } // ProducerThreadStatic
660 
661 
663 {
664  ULWord freqNdx(0), testPatNdx(0), badTally(0);
665  double timeOfLastSwitch (0.0);
666 
669  const bool isInterlace (!NTV2_VIDEO_FORMAT_HAS_PROGRESSIVE_PICTURE(mConfig.fVideoFormat));
670  const bool isPAL (NTV2_IS_PAL_VIDEO_FORMAT(mConfig.fVideoFormat));
671  const NTV2FrameRate ntv2FrameRate (::GetNTV2FrameRateFromVideoFormat(mConfig.fVideoFormat));
672  const TimecodeFormat tcFormat (CNTV2DemoCommon::NTV2FrameRate2TimecodeFormat(ntv2FrameRate));
673 
674  PLNOTE("Thread started");
675  while (!mGlobalQuit)
676  {
677  NTV2FrameData * pFrameData (mFrameDataRing.StartProduceNextBuffer());
678  if (!pFrameData)
679  { badTally++; // No frame available!
680  AJATime::Sleep(10); // Wait a bit for the consumer thread to free one up for me...
681  continue; // ...then try again
682  }
683 
684  if (pFrameData->VideoBuffer()) // Copy fresh, unmodified, pre-rendered test pattern into this frame's video buffer...
685  pFrameData->fVideoBuffer.CopyFrom (mTestPatRasters.at(testPatNdx),
686  /*srcOffset*/ 0,
687  /*dstOffset*/ 0,
688  /*byteCount*/ pFrameData->fVideoBuffer.GetByteCount());
689 
690  const CRP188 rp188Info (mCurrentFrame++, 0, 0, 10, tcFormat);
691  NTV2_RP188 tcF1, tcF2;
692  string tcString;
693 
694  rp188Info.GetRP188Reg(tcF1);
695  rp188Info.GetRP188Str(tcString);
696 
697  // Include timecode in output signal...
698  tcF2 = tcF1;
699  if (isInterlace)
700  { // Set bit 27 of Hi word (PAL) or Lo word (NTSC)
701  if (isPAL) tcF2.fHi |= BIT(27); else tcF2.fLo |= BIT(27);
702  }
703 
704  // Add timecodes for each SDI output...
705  for (NTV2TCIndexesConstIter it(mTCIndexes.begin()); it != mTCIndexes.end(); ++it)
706  pFrameData->fTimecodes[*it] = NTV2_IS_ATC_VITC2_TIMECODE_INDEX(*it) ? tcF2 : tcF1;
707 
708  if (pFrameData->VideoBuffer()) // Burn current timecode into the video buffer...
709  mTCBurner.BurnTimeCode (pFrameData->VideoBuffer(), tcString.c_str(), 80);
710  TCDBG("F" << DEC0N(mCurrentFrame-1,6) << ": " << tcF1 << ": " << tcString);
711 
712  // If also playing audio...
713  if (pFrameData->AudioBuffer()) // ...then generate audio tone data for this frame...
714  pFrameData->fNumAudioBytes = AddTone(*pFrameData); // ...and remember number of audio bytes to xfer
715 
716  // Every few seconds, change the test pattern and tone frequency...
717  const double currentTime (timeBase.FramesToSeconds(mCurrentFrame));
718  if (currentTime > timeOfLastSwitch + 4.0)
719  {
720  freqNdx = (freqNdx + 1) % gNumFrequencies;
721  testPatNdx = (testPatNdx + 1) % ULWord(mTestPatRasters.size());
722  mToneFrequency = gFrequencies[freqNdx];
723  timeOfLastSwitch = currentTime;
724  if (sTotalAncFileBytes)
725  PLDBG("F" << DEC0N(mCurrentFrame,6) << ": " << tcString << ": tone=" << mToneFrequency << "Hz, pattern='"
726  << tpNames.at(testPatNdx) << "', anc file " << DEC(sCurrentAncFileBytes * 100ULL / sTotalAncFileBytes) << "%");
727  else
728  PLDBG("F" << DEC0N(mCurrentFrame,6) << ": " << tcString << ": tone=" << mToneFrequency << "Hz, pattern='"
729  << tpNames.at(testPatNdx) << "'");
730  } // if time to switch test pattern & tone frequency
731 
732  // Signal that I'm done producing this FrameData, making it immediately available for transfer/playout...
733  mFrameDataRing.EndProduceNextBuffer();
734 
735  } // loop til mGlobalQuit goes true
736  PLNOTE("Thread completed: " << DEC(mCurrentFrame) << " frame(s) produced, " << DEC(badTally) << " failed");
737 
738 } // ProduceFrames
739 
740 
741 uint32_t NTV2Player::AddTone (NTV2FrameData & inFrameData)
742 {
745  ULWord numChannels (0);
746 
747  mDevice.GetFrameRate (frameRate, mConfig.fOutputChannel);
748  mDevice.GetAudioRate (audioRate, mAudioSystem);
749  mDevice.GetNumberAudioChannels (numChannels, mAudioSystem);
750 
751  // Set per-channel tone frequencies...
752  double pFrequencies [kNumAudioChannelsMax];
753  pFrequencies[0] = (mToneFrequency / 2.0);
754  for (ULWord chan(1); chan < numChannels; chan++)
755  // The 1.154782 value is the 16th root of 10, to ensure that if mToneFrequency is 2000,
756  // that the calculated frequency of audio channel 16 will be 20kHz...
757  pFrequencies[chan] = pFrequencies[chan-1] * 1.154782;
758 
759  // Since audio on AJA devices use fixed sample rates (typically 48KHz), certain video frame rates will
760  // necessarily result in some frames having more audio samples than others. GetAudioSamplesPerFrame is
761  // called to calculate the correct sample count for the current frame...
762  const ULWord numSamples (::GetAudioSamplesPerFrame (frameRate, audioRate, mCurrentFrame));
763  const double sampleRateHertz (::GetAudioSamplesPerSecond(audioRate));
764 
765  return ::AddAudioTone ( inFrameData.AudioBuffer(), // audio buffer to fill
766  mCurrentSample, // which sample for continuing the waveform
767  numSamples, // number of samples to generate
768  sampleRateHertz, // sample rate [Hz]
769  gAmplitudes, // per-channel amplitudes
770  pFrequencies, // per-channel tone frequencies [Hz]
771  31, // bits per sample
772  false, // don't byte-swap
773  numChannels); // number of audio channels to generate
774 } // AddTone
775 
776 
778 {
779  mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outStatus);
780 }
ULWord GetVideoWriteSize(ULWord inPageSize=4096UL) const
bool SetOutputTimeCodes(const NTV2TimeCodes &inValues)
Intended for playout, replaces the contents of my acOutputTimeCodes member.
NTV2FrameRate GetNTV2FrameRateFromVideoFormat(const NTV2VideoFormat inVideoFormat)
Definition: ntv2utils.cpp:3630
virtual void StartProducerThread(void)
Starts my producer thread.
Definition: ntv2player.cpp:643
double FramesToSeconds(int64_t frames) const
Definition: timebase.cpp:197
virtual bool SetTaskMode(const NTV2TaskMode inMode)
Sets the device&#39;s task mode.
#define NTV2_IS_VALID_TASK_MODE(__m__)
static const uint32_t gAudMaxSizeBytes(256 *1024)
The maximum number of bytes of 48KHz audio that can be transferred for a single frame. Worst case, assuming 16 channels of audio (max), 4 bytes per sample, and 67 msec per frame (assuming the lowest possible frame rate of 14.98 fps)... 48,000 samples per second requires 3,204 samples x 4 bytes/sample x 16 = 205,056 bytes 201K min will suffice, with 768 bytes to spare But it could be more efficient for page-aligned (and page-locked) memory to round to 256K.
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...
virtual bool SetAudioLoopBack(const NTV2AudioLoopBack inMode, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Enables or disables NTV2AudioLoopBack mode for the given NTV2AudioSystem.
Definition: ntv2audio.cpp:300
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...
virtual bool ReleaseStreamForApplication(ULWord inApplicationType, int32_t inProcessID)
Releases exclusive use of the AJA device for the given process, permitting other processes to acquire...
virtual AJAStatus SetUpTestPatternBuffers(void)
Creates my test pattern buffers.
Definition: ntv2player.cpp:348
AJAStatus Add(FrameDataPtr pInFrameData)
Appends a new frame buffer to me, increasing my frame storage capacity by one frame.
The NTV2 test pattern generator.
#define DEC0N(__x__, __n__)
#define BIT(_x_)
Definition: ajatypes.h:578
virtual bool SetVideoFormat(const NTV2VideoFormat inVideoFormat, const bool inIsAJARetail=(!(0)), const bool inKeepVancSettings=(0), const NTV2Channel inChannel=NTV2_CHANNEL1)
Configures the AJA device to handle a specific video format.
AJAStatus
Definition: types.h:380
virtual bool IsDeviceReady(const bool inCheckValid=(0))
static uint64_t GetPid()
Definition: process.cpp:35
#define AJA_FAILURE(_status_)
Definition: types.h:373
Declares the NTV2TestPatternGen class.
#define NTV2_VIDEO_FORMAT_HAS_PROGRESSIVE_PICTURE(__f__)
Definition: ntv2enums.h:1049
virtual bool GetAudioRate(NTV2AudioRate &outRate, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Returns the current NTV2AudioRate for the given Audio System.
Definition: ntv2audio.cpp:226
ULWord GetByteCount(void) const
virtual bool DMAWriteFrame(const ULWord inFrameNumber, const ULWord *pInFrameBuffer, const ULWord inByteCount)
Transfers a single frame from the host to the AJA device.
Definition: ntv2dma.cpp:65
virtual AJAStatus SetPriority(AJAThreadPriority priority)
Definition: thread.cpp:133
FrameDataPtr StartConsumeNextBuffer(void)
The thread that&#39;s responsible for processing incoming frames – the consumer – calls this function t...
if(!(riid==IID_IUnknown) &&!(riid==IID_IClassFactory))
Definition: dllentry.cpp:196
ULWord GetTotalBytes(void) const
bool CanAcceptMoreOutputFrames(void) const
#define NTV2_IS_2K_1080_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:763
bool fDoABConversion
If true, do level-A/B conversion; otherwise don&#39;t.
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
virtual AJAStatus Start()
Definition: thread.cpp:91
void EndConsumeNextBuffer(void)
The consumer thread calls this function to signal that it has finished processing the frame it obtain...
Declares common audio macros and structs used in the SDK.
std::string fDeviceSpec
The AJA device to use.
#define false
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.
static void ProducerThreadStatic(AJAThread *pThread, void *pContext)
This is the producer thread&#39;s static callback function that gets called when the producer thread star...
Definition: ntv2player.cpp:653
virtual bool GetEnabledChannels(NTV2ChannelSet &outChannels)
Answers with the set of channels that are currently enabled.
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.
virtual class DeviceCapabilities & features(void)
Definition: ntv2card.h:148
virtual bool GetAncRegionOffsetFromBottom(ULWord &outByteOffsetFromBottom, const NTV2AncillaryDataRegion inAncRegion=NTV2_AncRgn_All)
Answers with the byte offset to the start of an ancillary data region within a device frame buffer...
Definition: ntv2dma.cpp:601
virtual bool SetMultiFormatMode(const bool inEnable)
Enables or disables multi-format (per channel) device operation. If enabled, each device channel can ...
virtual bool ClearRouting(void)
Removes all existing signal path connections between any and all widgets on the AJA device...
Declares the AJATimeBase class.
This struct replaces the old RP188_STRUCT.
static const double gFrequencies[]
Definition: ntv2player.cpp:49
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
virtual bool IsRemote(void) const
ULWord numPixels
Width – total number of pixels per line.
virtual bool Active()
Definition: thread.cpp:116
virtual bool GetTaskMode(NTV2TaskMode &outMode)
Retrieves the device&#39;s current task mode.
bool WithAudio(void) const
virtual bool SetHDMIOutAudioRate(const NTV2AudioRate inNewValue, const NTV2Channel inWhichHDMIOut=NTV2_CHANNEL1)
Sets the HDMI output&#39;s audio rate.
Definition: ntv2audio.cpp:1009
bool Deallocate(void)
Deallocates my user-space storage (if I own it – i.e. from a prior call to Allocate).
static AJA_PixelFormat GetAJAPixelFormat(const NTV2PixelFormat inFormat)
This selects audio channels 1 thru 8.
Definition: ntv2enums.h:3322
NTV2FrameRate
Identifies a particular video frame rate.
Definition: ntv2enums.h:412
bool fTransmitLTC
If true, embed LTC; otherwise embed VITC.
virtual bool DrawTestPattern(const std::string &inTPName, const NTV2FormatDescriptor &inFormatDesc, NTV2Buffer &inBuffer)
Renders the given test pattern or color into a host raster buffer.
NTV2Standard
Identifies a particular video standard.
Definition: ntv2enums.h:165
#define TCDBG(_expr_)
Definition: ntv2player.cpp:27
virtual std::string GetDescription(void) const
Definition: ntv2card.cpp:139
static TimecodeFormat NTV2FrameRate2TimecodeFormat(const NTV2FrameRate inFrameRate)
static const ULWord gNumFrequencies(sizeof(gFrequencies)/sizeof(double))
#define NTV2_IS_PAL_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:733
NTV2InputXptID GetOutputDestInputXpt(const NTV2OutputDestination inOutputDest, const bool inIsSDI_DS2=false, const UWord inHDMI_Quadrant=99)
virtual bool IsOpen(void) const
virtual bool UnsubscribeOutputVerticalEvent(const NTV2Channel inChannel)
Unregisters me so I&#39;m no longer notified when an output VBI is signaled on the given output channel...
#define NTV2_IS_ATC_VITC2_TIMECODE_INDEX(__x__)
Definition: ntv2enums.h:3991
static bool GetFirstDeviceFromArgument(const std::string &inArgument, CNTV2Card &outDevice)
Rescans the host, and returns an open CNTV2Card instance for the AJA device that matches a command li...
virtual bool SetSDITransmitEnable(const NTV2Channel inChannel, const bool inEnable)
Sets the specified bidirectional SDI connector to act as an input or an output.
virtual bool 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 AcquireStreamForApplication(ULWord inApplicationType, int32_t inProcessID)
Reserves exclusive use of the AJA device for a given process, preventing other processes on the host ...
virtual bool DMABufferLock(const NTV2Buffer &inBuffer, bool inMap=(0), bool inRDMA=(0))
Page-locks the given host buffer to reduce transfer time and CPU usage of DMA transfers.
Definition: ntv2dma.cpp:429
Declares the AJAFileIO class.
#define AJA_NULL
Definition: ajatypes.h:167
void SetAbortFlag(const bool *pAbortFlag)
Tells me the boolean variable I should monitor such that when it gets set to "true" will cause any th...
virtual std::string GetDisplayName(void)
Answers with this device&#39;s display name.
Definition: ntv2card.cpp:88
NTV2InputXptID GetCSCInputXptFromChannel(const NTV2Channel inCSC, const bool inIsKeyInput=false)
Describes a video frame for a given video standard or format and pixel format, including the total nu...
static void Sleep(const int32_t inMilliseconds)
Suspends execution of the current thread for a given number of milliseconds.
Definition: systemtime.cpp:284
NTV2PixelFormat fPixelFormat
The pixel format to use.
virtual void ProduceFrames(void)
My producer thread that repeatedly produces video frames.
Definition: ntv2player.cpp:662
2: OEM (recommended): device configured by client application(s) with some driver involvement...
std::vector< std::string > NTV2StringList
Definition: ntv2utils.h:1155
static const double gAmplitudes[]
Definition: ntv2player.cpp:51
virtual bool SetSDIOutputAudioSystem(const NTV2Channel inSDIOutputConnector, const NTV2AudioSystem inAudioSystem)
Sets the device&#39;s NTV2AudioSystem that will provide audio for the given SDI output&#39;s audio embedder...
virtual uint32_t AddTone(NTV2FrameData &inFrameData)
Inserts audio tone (based on my current tone frequency) into the given NTV2FrameData&#39;s audio buffer...
Definition: ntv2player.cpp:741
virtual AJAStatus SetUpAudio(void)
Performs all audio setup.
Definition: ntv2player.cpp:260
#define PLNOTE(_xpr_)
NTV2VideoFormat fVideoFormat
The video format to use.
std::string NTV2VideoFormatToString(const NTV2VideoFormat inValue, const bool inUseFrameRate=false)
Definition: ntv2utils.cpp:6746
Embeds silence (zeroes) into the data stream.
Definition: ntv2enums.h:2030
virtual bool SetVANCShiftMode(NTV2Channel inChannel, NTV2VANCDataShiftMode inMode)
Enables or disables the "VANC Shift Mode" feature for the given channel.
static ULWord gAncMaxSizeBytes(NTV2_ANCSIZE_MAX)
The maximum number of bytes of ancillary data that can be transferred for a single field...
AJA_EXPORT bool RenderTimeCodeFont(AJA_PixelFormat pixelFormat, uint32_t numPixels, uint32_t numLines)
virtual bool DMABufferUnlockAll()
Unlocks all previously-locked buffers used for DMA transfers.
Definition: ntv2dma.cpp:457
Specifies the PTP source on SFP 1.
Definition: ntv2enums.h:1468
bool IsVideoFormatA(const NTV2VideoFormat format)
Definition: ntv2utils.cpp:5458
#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 AJAStatus SetUpVideo(void)
Performs all video setup.
Definition: ntv2player.cpp:189
virtual void ConsumeFrames(void)
My consumer thread that repeatedly plays frames using AutoCirculate (until quit). ...
Definition: ntv2player.cpp:496
Declares the CNTV2DeviceScanner class.
NTV2Player(const PlayerConfig &inConfig)
Constructs me using the given configuration settings.
Definition: ntv2player.cpp:55
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...
bool AddAudioTone(ULWord &outNumBytesWritten, NTV2Buffer &inAudioBuffer, ULWord &inOutCurrentSample, const ULWord inNumSamples, const double inSampleRate, const double inAmplitude, const double inFrequency, const ULWord inNumBits, const bool inByteSwap, const ULWord inNumChannels)
Fills the given buffer with 32-bit (ULWord) audio tone samples.
Definition: ntv2utils.cpp:4413
Declares the AJAProcess class.
Describes a user-space buffer on the host computer. I have an address and a length, plus some optional attributes (allocated by SDK?, page-aligned? etc.).
#define PLFAIL(_xpr_)
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).
bool fDoMultiFormat
If true, enable device-sharing; otherwise take exclusive control of device.
static NTV2TestPatternNames getTestPatternNames(void)
uint16_t GetEndFrame(void) const
NTV2Buffer & AudioBuffer(void)
bool IsRGBFormat(const NTV2FrameBufferFormat format)
Definition: ntv2utils.cpp:5410
virtual AJAStatus SetUpHostBuffers(void)
Sets up my host video & audio buffers.
Definition: ntv2player.cpp:303
This object specifies the information that will be transferred to or from the AJA device in the CNTV2...
static const bool BUFFER_PAGE_ALIGNED((!(0)))
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 bool GetNumberAudioChannels(ULWord &outNumChannels, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Returns the current number of audio channels being captured or played by a given Audio System on the ...
Definition: ntv2audio.cpp:180
I play out SD or HD test pattern (with timecode) to an output of an AJA device with or without audio ...
Definition: ntv2player.h:24
virtual ~NTV2Player(void)
Definition: ntv2player.cpp:76
#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.
std::set< NTV2Channel > NTV2ChannelSet
A set of distinct NTV2Channel values.
void EndProduceNextBuffer(void)
The producer thread calls this function to signal that it has finished populating the frame it obtain...
This identifies the first Audio System.
Definition: ntv2enums.h:3897
virtual bool WaitForOutputVerticalInterrupt(const NTV2Channel inChannel=NTV2_CHANNEL1, UWord inRepeatCount=1)
Efficiently sleeps the calling thread/process until the next one or more field (interlaced video) or ...
#define TCNOTE(_expr_)
Definition: ntv2player.cpp:25
NTV2Channel fOutputChannel
The device channel to use.
static const size_t CIRCULAR_BUFFER_SIZE(10)
Number of NTV2FrameData&#39;s in our ring.
static const ULWord kDemoAppSignature((((uint32_t)( 'D'))<< 24)|(((uint32_t)( 'E'))<< 16)|(((uint32_t)( 'M'))<< 8)|(((uint32_t)( 'O'))<< 0))
ULWord numLines
Height – total number of lines.
virtual bool DisableChannels(const NTV2ChannelSet &inChannels)
Disables the given FrameStore(s).
virtual AJAStatus Attach(AJAThreadFunction *pThreadFunction, void *pUserContext)
Definition: thread.cpp:169
FrameDataPtr StartProduceNextBuffer(void)
The thread that&#39;s responsible for providing frames – the producer – calls this function to populate...
double GetAudioSamplesPerSecond(const NTV2AudioRate inAudioRate)
Returns the audio sample rate as a number of audio samples per second.
Definition: ntv2utils.cpp:3303
Identifies the "normal" Field 2 ancillary data region.
Definition: ntv2enums.h:4230
mFormatDesc
Definition: ntv2vcam.cpp:942
virtual bool SetSDIOutLevelAtoLevelBConversion(const UWord inOutputSpigot, const bool inEnable)
Enables or disables 3G level A to 3G level B conversion at the SDI output widget (assuming the AJA de...
virtual bool SetHDMIOutAudioSource8Channel(const NTV2Audio8ChannelSelect inNewValue, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1, const NTV2Channel inWhichHDMIOut=NTV2_CHANNEL1)
Changes the HDMI output&#39;s 8-channel audio source.
Definition: ntv2audio.cpp:935
This is returned from the CNTV2Card::AutoCirculateGetStatus function.
NTV2OutputXptID GetFrameStoreOutputXptFromChannel(const NTV2Channel inFrameStore, const bool inIsRGB=false, const bool inIs425=false)
virtual bool SetHDMIOutAudioFormat(const NTV2AudioFormat inNewValue, const NTV2Channel inWhichHDMIOut=NTV2_CHANNEL1)
Sets the HDMI output&#39;s audio format.
Definition: ntv2audio.cpp:1031
uint16_t UWord
Definition: ajatypes.h:221
ULWord GetAudioSamplesPerFrame(const NTV2FrameRate inFrameRate, const NTV2AudioRate inAudioRate, ULWord inCadenceFrame=0, bool inIsSMPTE372Enabled=false)
Returns the number of audio samples for a given video frame rate, audio sample rate, and frame number. This is useful since AJA devices use fixed audio sample rates (typically 48KHz), and some video frame rates will necessarily result in some frames having more audio samples than others.
Definition: ntv2utils.cpp:2889
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1359
static bool FileExists(const std::wstring &fileName)
Definition: file_io.cpp:97
virtual bool AutoCirculateStart(const NTV2Channel inChannel, const ULWord64 inStartTime=0)
Starts AutoCirculating the specified channel that was previously initialized by CNTV2Card::AutoCircul...
bool CanDoFrameBufferFormat(const NTV2PixelFormat inPF)
virtual bool SubscribeOutputVerticalEvent(const NTV2Channel inChannel)
Causes me to be notified when an output vertical blanking interrupt is generated for the given output...
virtual AJAStatus Run(void)
Runs me.
Definition: ntv2player.cpp:457
virtual void Quit(void)
Gracefully stops me from running.
Definition: ntv2player.cpp:85
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__)
UWord GetNumAnalogVideoOutputs(void)
TimecodeFormat
Definition: ntv2rp188.h:22
virtual bool GetFrameRate(NTV2FrameRate &outValue, NTV2Channel inChannel=NTV2_CHANNEL1)
Returns the AJA device&#39;s currently configured frame rate via its "value" parameter.
static AJA_FrameRate GetAJAFrameRate(const NTV2FrameRate inFrameRate)
static uint64_t sTotalAncFileBytes(0)
AJA_EXPORT bool BurnTimeCode(void *pBaseVideoAddress, const std::string &inTimeCodeStr, const uint32_t inYPercent)
I encapsulate the video, audio and anc host buffers used in the AutoCirculate demos. I&#39;m a more modern version of the AVDataBuffer.
NTV2AudioSystem NTV2ChannelToAudioSystem(const NTV2Channel inChannel)
Converts the given NTV2Channel value into its equivalent NTV2AudioSystem.
Definition: ntv2utils.cpp:4869
enum NTV2InputCrosspointID NTV2InputXptID
NTV2ACFrameRange fFrames
AutoCirculate frame count or range.
NTV2Standard GetNTV2StandardFromVideoFormat(const NTV2VideoFormat inVideoFormat)
Definition: ntv2utils.cpp:2375
virtual bool SetSDIOutputDS2AudioSystem(const NTV2Channel inSDIOutputConnector, const NTV2AudioSystem inAudioSystem)
Sets the Audio System that will supply audio for the given SDI output&#39;s audio embedder for Data Strea...
Configures an NTV2Player instance.
bool GetRP188Reg(RP188_STRUCT &outRP188) const
Definition: ntv2rp188.cpp:1241
NTV2AudioRate
Definition: ntv2enums.h:1928
ULWord fLo
| BG 4 | Secs10 | BG 3 | Secs 1 | BG 2 | Frms10 | BG 1 | Frms 1 |
virtual bool RouteOutputSignal(void)
Performs all widget/signal routing for playout.
Definition: ntv2player.cpp:399
static uint64_t sCurrentAncFileBytes(0)
static size_t SetDefaultPageSize(void)
#define PLWARN(_xpr_)
NTV2TCIndexes::const_iterator NTV2TCIndexesConstIter
bool CanDoVideoFormat(const NTV2VideoFormat inVF)
#define AUTOCIRCULATE_WITH_RP188
Use this to AutoCirculate with RP188.
virtual void StartConsumerThread(void)
Starts my consumer thread.
Definition: ntv2player.cpp:471
const char * NTV2FrameBufferFormatString(NTV2FrameBufferFormat fmt)
Definition: ntv2debug.cpp:214
bool GetRP188Str(std::string &sRP188) const
Definition: ntv2rp188.cpp:918
bool WithVideo(void) const
virtual void GetACStatus(AUTOCIRCULATE_STATUS &outStatus)
Provides status information about my output (playout) process.
Definition: ntv2player.cpp:777
bool SetAudioBuffer(ULWord *pInAudioBuffer, const ULWord inAudioByteCount)
Sets my audio buffer for use in a subsequent call to CNTV2Card::AutoCirculateTransfer.
virtual bool SetSDIOutputStandard(const UWord inOutputSpigot, const NTV2Standard inValue)
Sets the SDI output spigot&#39;s video standard.
NTV2Buffer acANCBuffer
The host ancillary data buffer. This field is owned by the client application, and thus is responsibl...
#define PLDBG(_xpr_)
NTV2InputXptID GetSDIOutputInputXpt(const NTV2Channel inSDIOutput, const bool inIsDS2=false)
virtual AJAStatus Init(void)
Initializes me and prepares me to Run.
Definition: ntv2player.cpp:108
virtual bool SetVANCMode(const NTV2VANCMode inVancMode, const NTV2Channel inChannel=NTV2_CHANNEL1)
Sets the VANC mode for the given FrameStore.
static void ConsumerThreadStatic(AJAThread *pThread, void *pContext)
This is the consumer thread&#39;s static callback function that gets called when the consumer thread star...
Definition: ntv2player.cpp:482
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
ULWord fHi
| BG 8 | Hrs 10 | BG 7 | Hrs 1 | BG 6 | Mins10 | BG 5 | Mins 1 |
enum NTV2OutputCrosspointID NTV2OutputXptID
uint16_t GetStartFrame(void) const
NTV2OutputXptID GetCSCOutputXptFromChannel(const NTV2Channel inCSC, const bool inIsKey=false, const bool inIsRGB=false)
#define NTV2_ANCSIZE_MAX
This identifies the mode in which there are no VANC lines in the frame buffer.
Definition: ntv2enums.h:3799
bool SetVideoBuffer(ULWord *pInVideoBuffer, const ULWord inVideoByteCount)
Sets my video buffer for use in a subsequent call to CNTV2Card::AutoCirculateTransfer.
std::string fAncDataFilePath
Optional path to Anc binary data file to playout.
virtual bool EnableChannel(const NTV2Channel inChannel)
Enables the given FrameStore.