AJA NTV2 SDK  18.1.0.2149
NTV2 SDK 18.1.0.2149
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  { if (aja::lower(mConfig.fDeviceSpec) != "list" && mConfig.fDeviceSpec != "?")
115  cerr << "## ERROR: Device '" << mConfig.fDeviceSpec << "' not found" << endl;
116  return AJA_STATUS_OPEN;
117  }
118  if (!mDevice.IsDeviceReady(false))
119  {cerr << "## ERROR: Device '" << mDevice.GetDescription() << "' not ready" << endl; return AJA_STATUS_INITIALIZE;}
120  if (!mDevice.features().CanDoPlayback())
121  {cerr << "## ERROR: '" << mDevice.GetDescription() << "' is capture-only" << endl; return AJA_STATUS_FEATURE;}
122 
123  const UWord maxNumChannels (mDevice.features().GetNumFrameStores());
124 
125  // Beware -- some older devices (e.g. Corvid1) can only output from FrameStore 2...
126  if (mConfig.fOutputChannel == NTV2_CHANNEL1 && !mDevice.features().CanDoFrameStore1Display())
127  mConfig.fOutputChannel = NTV2_CHANNEL2;
128  if (UWord(mConfig.fOutputChannel) >= maxNumChannels)
129  {
130  cerr << "## ERROR: '" << mDevice.GetDescription() << "' can't use Ch" << DEC(mConfig.fOutputChannel+1)
131  << " -- only supports Ch1" << (maxNumChannels > 1 ? string("-Ch") + string(1, char(maxNumChannels+'0')) : "") << endl;
132  return AJA_STATUS_UNSUPPORTED;
133  }
134 
135  if (!mConfig.fAncDataFilePath.empty())
137  {
138  cerr << "## ERROR: Anc data file '" << mConfig.fAncDataFilePath << "' not found" << endl;
139  return AJA_STATUS_NOT_FOUND;
140  }
141 
142  if (!mConfig.fDoMultiFormat)
143  {
144  mDevice.GetTaskMode(mSavedTaskMode); // Save the current task mode
146  { cerr << "## ERROR: '" << mDevice.GetDescription() << "' is in use by another process" << endl;
147  return AJA_STATUS_BUSY; // Device is in use by another app -- fail
148  }
149  }
150  mDevice.SetTaskMode(NTV2_OEM_TASKS); // Set OEM service level
151 
152  if (mDevice.features().CanDoMultiFormat())
153  mDevice.SetMultiFormatMode(mConfig.fDoMultiFormat);
154  else
155  mConfig.fDoMultiFormat = false;
156 
157  // Set up the video and audio...
158  status = SetUpVideo();
159  if (AJA_FAILURE(status))
160  return status;
161  status = mConfig.WithAudio() ? SetUpAudio() : AJA_STATUS_SUCCESS;
162  if (AJA_FAILURE(status))
163  return status;
164 
165  // Set up the circular buffers, and the test pattern buffers...
166  status = SetUpHostBuffers();
167  if (AJA_FAILURE(status))
168  return status;
169  status = SetUpTestPatternBuffers();
170  if (AJA_FAILURE(status))
171  return status;
172 
173  // Set up the device signal routing...
174  RouteOutputSignal(); // (Ignore routing failures)
175 
176  // Lastly, prepare my AJATimeCodeBurn instance...
177  if (!mTCBurner.RenderTimeCodeFont (CNTV2DemoCommon::GetAJAPixelFormat(mConfig.fPixelFormat), mFormatDesc.numPixels, mFormatDesc.numLines))
178  {cerr << "## ERROR: RenderTimeCodeFont failed for: " << mFormatDesc << endl; return AJA_STATUS_UNSUPPORTED;}
179 
180  // Ready to go...
181  #if defined(_DEBUG)
182  cerr << mConfig
183  << "Device Description: " << mDevice.GetDescription() << endl
184  << endl;
185  #endif // defined(_DEBUG)
186  return AJA_STATUS_SUCCESS;
187 
188 } // Init
189 
190 
192 {
193  // Configure the device to output the requested video format...
194  if (mConfig.fVideoFormat == NTV2_FORMAT_UNKNOWN)
195  {cerr << "## ERROR: unknown video format" << endl; return AJA_STATUS_BAD_PARAM;}
196  if (!mDevice.features().CanDoVideoFormat(mConfig.fVideoFormat))
197  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' doesn't support "
198  << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << endl;
199  return AJA_STATUS_UNSUPPORTED;
200  }
201  if (!mDevice.features().CanDoFrameBufferFormat(mConfig.fPixelFormat))
202  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' doesn't support "
203  << ::NTV2FrameBufferFormatString(mConfig.fPixelFormat) << endl;
204  return AJA_STATUS_UNSUPPORTED;
205  }
206 
207  // This demo doesn't playout dual-link RGB over SDI -- only YCbCr.
208  // Check that this device has a CSC to convert RGB to YUV...
209  if (::IsRGBFormat(mConfig.fPixelFormat) && UWord(mConfig.fOutputChannel) > mDevice.features().GetNumCSCs())
210  { cerr << "## ERROR: No CSC for channel " << DEC(mConfig.fOutputChannel+1) << " to convert RGB pixel format" << endl;
211  return AJA_STATUS_UNSUPPORTED;
212  }
213  if (!mDevice.features().CanDo3GLevelConversion() && mConfig.fDoABConversion && ::IsVideoFormatA(mConfig.fVideoFormat))
214  mConfig.fDoABConversion = false;
215  if (mConfig.fDoABConversion)
217 
218  // Keep the raster description handy...
219  mFormatDesc = NTV2FormatDescriptor(mConfig.fVideoFormat, mConfig.fPixelFormat);
220  if (!mFormatDesc.IsValid())
221  { cerr << "## ERROR: " << mDevice.GetDescription() << ": bad raster descriptor for " << ::NTV2VideoFormatToString(mConfig.fVideoFormat)
222  << " and " << ::NTV2FrameBufferFormatToString(mConfig.fPixelFormat) << endl;
223  return AJA_STATUS_FAIL;
224  }
225 
226  // If we own the whole device, make sure all FrameStores are disabled (good practice)
227  if (!mConfig.fDoMultiFormat)
228  {
229  NTV2ChannelSet enabledChannels;
230  mDevice.GetEnabledChannels(enabledChannels);
231  mDevice.DisableChannels(enabledChannels);
232  }
233 
234  // Turn on the FrameStore (to read frame buffer memory and transmit video)...
235  mDevice.EnableChannel(mConfig.fOutputChannel);
236 
237  // This demo assumes VANC is disabled...
238  mDevice.SetVANCMode(NTV2_VANCMODE_OFF, mConfig.fOutputChannel);
240 
241  // Set the FrameStore video format...
242  mDevice.SetVideoFormat (mConfig.fVideoFormat, false, false, mConfig.fOutputChannel);
243 
244  // Set the frame buffer pixel format for the device FrameStore...
245  mDevice.SetFrameBufferFormat (mConfig.fOutputChannel, mConfig.fPixelFormat);
246 
247  // The output interrupt is Enabled by default, but on some platforms, you must subscribe to it
248  // in order to be able to wait on its event/semaphore...
250 
251  // Get current per-field maximum Anc buffer size...
254 
255  // Set output clock reference...
257 
258  // At this point, video setup is complete (except for widget signal routing).
259  return AJA_STATUS_SUCCESS;
260 
261 } // SetUpVideo
262 
263 
265 {
266  uint16_t numAudioChannels (mDevice.features().GetMaxAudioChannels());
267  if (numAudioChannels > 8) // If audio system handles more than 8 channels...
268  if (!mDevice.features().CanDo2110()) // ...and SDI (i.e. not ST 2110 IP streaming)...
269  if (NTV2_IS_2K_1080_VIDEO_FORMAT(mConfig.fVideoFormat)) // ...and 2K (narrower HANC only fits 8 audio channels)
270  numAudioChannels = 8; // ...then reduce to 8 audio channels
271 
272  mAudioSystem = NTV2_AUDIOSYSTEM_1; // Use NTV2_AUDIOSYSTEM_1...
273  if (mDevice.features().GetNumAudioSystems() > 1) // ...but if the device has more than one audio system...
274  mAudioSystem = ::NTV2ChannelToAudioSystem(mConfig.fOutputChannel); // ...base it on the channel
275  // However, there are a few older devices that have only 1 audio system,
276  // yet 2 frame stores (or must use channel 2 for playout)...
277  if (!mDevice.features().CanDoFrameStore1Display())
278  mAudioSystem = NTV2_AUDIOSYSTEM_1;
279 
280  mDevice.SetNumberAudioChannels (numAudioChannels, mAudioSystem);
281  mDevice.SetAudioRate (NTV2_AUDIO_48K, mAudioSystem);
282 
283  // How big should the on-device audio buffer be? 1MB? 2MB? 4MB? 8MB?
284  // For this demo, 4MB will work best across all platforms (Windows, Mac & Linux)...
285  mDevice.SetAudioBufferSize (NTV2_AUDIO_BUFFER_BIG, mAudioSystem);
286 
287  // Set the SDI output audio embedders to embed audio samples from the output of mAudioSystem...
288  mDevice.SetSDIOutputAudioSystem (mConfig.fOutputChannel, mAudioSystem);
289  mDevice.SetSDIOutputDS2AudioSystem (mConfig.fOutputChannel, mAudioSystem);
290 
291  // If the last app using the device left it in E-E mode (input passthru), then loopback
292  // must be disabled --- otherwise the output audio will be pass-thru SDI input audio...
293  mDevice.SetAudioLoopBack (NTV2_AUDIO_LOOPBACK_OFF, mAudioSystem);
294 
295  if (!mConfig.fDoMultiFormat && mDevice.features().GetNumHDMIVideoOutputs())
296  {
300  }
301  return AJA_STATUS_SUCCESS;
302 
303 } // SetUpAudio
304 
305 
307 {
308  CNTV2DemoCommon::SetDefaultPageSize(); // Set host-specific page size
309 
310  // Let my circular buffer know when it's time to quit...
311  mFrameDataRing.SetAbortFlag (&mGlobalQuit);
312 
313  // Allocate and add each in-host NTV2FrameData to my circular buffer member variable...
314  mHostBuffers.reserve(CIRCULAR_BUFFER_SIZE);
315  while (mHostBuffers.size() < CIRCULAR_BUFFER_SIZE)
316  {
317  mHostBuffers.push_back(NTV2FrameData()); // Make a new NTV2FrameData...
318  NTV2FrameData & frameData(mHostBuffers.back()); // ...and get a reference to it
319 
320  // Allocate a page-aligned video buffer
321  if (mConfig.WithVideo())
322  if (!frameData.fVideoBuffer.Allocate (mFormatDesc.GetTotalBytes(), BUFFER_PAGE_ALIGNED))
323  {
324  PLFAIL("Failed to allocate " << xHEX0N(mFormatDesc.GetTotalBytes(),8) << "-byte video buffer");
325  return AJA_STATUS_MEMORY;
326  }
327  #ifdef NTV2_BUFFER_LOCKING
328  if (frameData.fVideoBuffer)
329  mDevice.DMABufferLock(frameData.fVideoBuffer, true);
330  #endif
331 
332  // Allocate a page-aligned audio buffer (if transmitting audio)
333  if (mConfig.WithAudio())
334  if (!frameData.fAudioBuffer.Allocate (gAudMaxSizeBytes, BUFFER_PAGE_ALIGNED))
335  {
336  PLFAIL("Failed to allocate " << xHEX0N(gAudMaxSizeBytes,8) << "-byte audio buffer");
337  return AJA_STATUS_MEMORY;
338  }
339  #ifdef NTV2_BUFFER_LOCKING
340  if (frameData.fAudioBuffer)
341  mDevice.DMABufferLock(frameData.fAudioBuffer, /*alsoPreLockSGL*/true);
342  #endif
343  mFrameDataRing.Add (&frameData);
344  } // for each NTV2FrameData
345 
346  return AJA_STATUS_SUCCESS;
347 
348 } // SetUpHostBuffers
349 
350 
352 {
353  vector<NTV2TestPatternSelect> testPatIDs;
354  testPatIDs.push_back(NTV2_TestPatt_ColorBars100);
355  testPatIDs.push_back(NTV2_TestPatt_ColorBars75);
356  testPatIDs.push_back(NTV2_TestPatt_Ramp);
357  testPatIDs.push_back(NTV2_TestPatt_MultiBurst);
358  testPatIDs.push_back(NTV2_TestPatt_LineSweep);
359  testPatIDs.push_back(NTV2_TestPatt_CheckField);
360  testPatIDs.push_back(NTV2_TestPatt_FlatField);
361  testPatIDs.push_back(NTV2_TestPatt_MultiPattern);
362 
363  mTestPatRasters.clear();
364  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
365  mTestPatRasters.push_back(NTV2Buffer());
366 
367  NTV2_ASSERT(mFormatDesc.IsValid() && "Bad format descriptor"); // (Already checked in SetupVideo)
368  if (mFormatDesc.IsVANC())
369  {cerr << "## ERROR: VANC should have been disabled: " << mFormatDesc << endl; return AJA_STATUS_FAIL;}
370 
371  // Set up one video buffer for each test pattern...
372  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
373  {
374  // Allocate the buffer memory...
375  if (!mTestPatRasters.at(tpNdx).Allocate (mFormatDesc.GetTotalBytes(), BUFFER_PAGE_ALIGNED))
376  { cerr << "## ERROR: Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << ": "
377  << xHEX0N(mFormatDesc.GetTotalBytes(),8) << "-byte page-aligned alloc failed" << endl;
378  return AJA_STATUS_MEMORY;
379  }
380 
381  // Fill the buffer with test pattern...
382  NTV2TestPatternGen testPatternGen;
383  if (!testPatternGen.DrawTestPattern (testPatIDs.at(tpNdx), mFormatDesc, mTestPatRasters.at(tpNdx)))
384  {
385  cerr << "## ERROR: DrawTestPattern " << DEC(tpNdx) << " failed: " << mFormatDesc << endl;
386  return AJA_STATUS_FAIL;
387  }
388 
389  #ifdef NTV2_BUFFER_LOCKING
390  // Try to prelock the memory, including its scatter-gather list...
391  if (!mDevice.DMABufferLock(mTestPatRasters.at(tpNdx), /*alsoLockSegmentMap=*/true))
392  cerr << "## WARNING: Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << " failed pre-lock" << endl;
393  #endif
394  } // loop for each predefined pattern
395 
396  return AJA_STATUS_SUCCESS;
397 
398 } // SetUpTestPatternBuffers
399 
400 
402 {
403  const NTV2Standard outputStandard (::GetNTV2StandardFromVideoFormat(mConfig.fVideoFormat));
404  const bool isRGB (::IsRGBFormat(mConfig.fPixelFormat));
405  const bool canVerify (mDevice.features().HasCrosspointConnectROM());
406  UWord connectFailures (0);
407 
408  // Since this function figures out which SDI spigots will be set up for output,
409  // it also sets the "mTCIndexes" member, which determines which timecodes will
410  // be transmitted (and on which SDI spigots)...
411  mTCIndexes.clear();
412 
413  const NTV2OutputXptID cscVidOutXpt(::GetCSCOutputXptFromChannel(mConfig.fOutputChannel, false/*isKey*/, !isRGB/*isRGB*/));
414  const NTV2OutputXptID fsVidOutXpt (::GetFrameStoreOutputXptFromChannel(mConfig.fOutputChannel, isRGB/*isRGB*/, false/*is425*/));
415  const NTV2InputXptID cscInputXpt (isRGB ? ::GetCSCInputXptFromChannel(mConfig.fOutputChannel, false/*isKeyInput*/) : NTV2_INPUT_CROSSPOINT_INVALID);
416 
417  if (!mConfig.fDoMultiFormat) // Not multiformat: We own the whole device...
418  mDevice.ClearRouting(); // Start with clean slate
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*/ ULWord(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:301
Specifies the device&#39;s internal clock.
Definition: ntv2enums.h:1462
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:351
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:596
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))
size_t GetByteCount(void) const
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:1051
virtual bool GetAudioRate(NTV2AudioRate &outRate, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Returns the current NTV2AudioRate for the given Audio System.
Definition: ntv2audio.cpp:227
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:765
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:206
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:236
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 ...
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:489
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:4964
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:1010
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:3325
NTV2FrameRate
Identifies a particular video frame rate.
Definition: ntv2enums.h:414
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:167
#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:735
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:3994
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:180
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...
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:264
#define PLNOTE(_xpr_)
NTV2VideoFormat fVideoFormat
The video format to use.
std::string NTV2VideoFormatToString(const NTV2VideoFormat inValue, const bool inUseFrameRate=false)
Definition: ntv2utils.cpp:6748
Embeds silence (zeroes) into the data stream.
Definition: ntv2enums.h:2033
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:1471
bool IsVideoFormatA(const NTV2VideoFormat format)
Definition: ntv2utils.cpp:5460
#define AUTOCIRCULATE_WITH_ANC
Use this to AutoCirculate with ancillary data.
Specifies channel or FrameStore 2 (or the 2nd item).
Definition: ntv2enums.h:1362
virtual AJAStatus SetUpVideo(void)
Performs all video setup.
Definition: ntv2player.cpp:191
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:5412
virtual AJAStatus SetUpHostBuffers(void)
Sets up my host video & audio buffers.
Definition: ntv2player.cpp:306
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:250
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:181
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:3900
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:4233
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:936
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:1032
uint16_t UWord
Definition: ajatypes.h:234
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:1361
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.
std::string NTV2FrameBufferFormatToString(const NTV2FrameBufferFormat inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:6938
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:4871
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:1931
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:401
static uint64_t sCurrentAncFileBytes(0)
static size_t SetDefaultPageSize(void)
#define PLWARN(_xpr_)
NTV2TCIndexes::const_iterator NTV2TCIndexesConstIter
std::vector< std::string > NTV2StringList
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:218
bool GetRP188Str(std::string &sRP188) const
Definition: ntv2rp188.cpp:918
std::string & lower(std::string &str)
Definition: common.cpp:436
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:147
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:3802
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.