AJA NTV2 SDK  18.1.0.2439
NTV2 SDK 18.1.0.2439
ntv2player8k.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2player8k.h"
9 #include "ntv2debug.h"
10 #include "ntv2devicescanner.h"
11 #include "ntv2testpatterngen.h"
13 #include "ajabase/system/process.h"
14 
15 using namespace std;
16 
17 #define NTV2_BUFFER_LOCKING // IMPORTANT FOR 8K: Define this to pre-lock video/audio buffers in kernel
18 
19 
25 static ULWord gAncMaxSizeBytes (NTV2_ANCSIZE_MAX); // Max per-frame anc buffer size, in bytes
26 
35 static const uint32_t gAudMaxSizeBytes (256 * 1024); // Max per-frame audio buffer size, in bytes
36 
37 static const bool BUFFER_PAGE_ALIGNED (true);
38 
39 // Audio tone generator data
40 static const double gFrequencies [] = {250.0, 500.0, 1000.0, 2000.0};
41 static const ULWord gNumFrequencies (sizeof(gFrequencies) / sizeof(double));
42 // Unlike NTV2Player, this demo uses the same waveform amplitude in each audio channel
43 
44 
46  : mConfig (inConfig),
47  mConsumerThread (),
48  mProducerThread (),
49  mDevice (),
50  mSavedTaskMode (NTV2_TASK_MODE_INVALID),
51  mCurrentFrame (0),
52  mCurrentSample (0),
53  mToneFrequency (440.0),
54  mAudioSystem (NTV2_AUDIOSYSTEM_INVALID),
55  mFormatDesc (),
56  mGlobalQuit (false),
57  mTCBurner (),
58  mHostBuffers (),
59  mFrameDataRing (),
60  mTestPatRasters ()
61 {
62 }
63 
64 
66 {
67  // Stop my playout and producer threads, then destroy them...
68  Quit();
69 
70  mDevice.UnsubscribeOutputVerticalEvent(mConfig.fOutputChannel); // Unsubscribe from output VBI event
71 } // destructor
72 
73 
74 void NTV2Player8K::Quit (void)
75 {
76  // Set the global 'quit' flag, and wait for the threads to go inactive...
77  mGlobalQuit = true;
78 
79  while (mProducerThread.Active())
80  AJATime::Sleep(10);
81 
82  while (mConsumerThread.Active())
83  AJATime::Sleep(10);
84 
85 #if defined(NTV2_BUFFER_LOCKING)
86  mDevice.DMABufferUnlockAll();
87 #endif // NTV2_BUFFER_LOCKING
88  if (!mConfig.fDoMultiFormat && mDevice.IsOpen())
89  {
91  if (NTV2_IS_VALID_TASK_MODE(mSavedTaskMode))
92  mDevice.SetTaskMode(mSavedTaskMode); // Restore prior task mode
93  }
94 } // Quit
95 
96 
98 {
100 
101  // Open the device...
103  { if (aja::lower(mConfig.fDeviceSpec) != "list" && mConfig.fDeviceSpec != "?")
104  cerr << "## ERROR: Device '" << mConfig.fDeviceSpec << "' not found" << endl;
105  return AJA_STATUS_OPEN;
106  }
107  if (!mDevice.IsDeviceReady(false))
108  {cerr << "## ERROR: Device '" << mConfig.fDeviceSpec << "' not ready" << endl; return AJA_STATUS_INITIALIZE;}
109  if (!mDevice.features().CanDoPlayback())
110  {cerr << "## ERROR: '" << mDevice.GetDescription() << "' is capture-only" << endl; return AJA_STATUS_FEATURE;}
111 
112  const UWord maxNumChannels (mDevice.features().GetNumFrameStores());
113 
114  // Check for an invalid configuration
116  {cerr << "## ERROR: HFR RGB output not supported" << endl; return AJA_STATUS_BAD_PARAM;}
117 
118  // Check for valid channel...
119  if (UWord(mConfig.fOutputChannel) >= maxNumChannels)
120  {
121  cerr << "## ERROR: Cannot use channel '" << DEC(mConfig.fOutputChannel+1) << "' -- device only supports channel 1"
122  << (maxNumChannels > 1 ? string(" thru ") + string(1, char(maxNumChannels+'0')) : "") << endl;
123  return AJA_STATUS_UNSUPPORTED;
124  }
125  if (mConfig.fOutputChannel != NTV2_CHANNEL1 && mConfig.fOutputChannel != NTV2_CHANNEL3)
126  {
127  cerr << "## ERROR: 8K/UHD2 requires Ch1 or Ch3, not Ch" << DEC(mConfig.fOutputChannel) << endl;
128  return AJA_STATUS_BAD_PARAM;
129  }
130 
131  if (!mConfig.fDoMultiFormat)
132  {
133  mDevice.GetTaskMode(mSavedTaskMode); // Save the current task mode
135  return AJA_STATUS_BUSY; // Device is in use by another app -- fail
136  }
137  mDevice.SetTaskMode(NTV2_OEM_TASKS); // Set OEM service level
138 
139  if (mDevice.features().CanDoMultiFormat())
140  mDevice.SetMultiFormatMode(mConfig.fDoMultiFormat);
141  else
142  mConfig.fDoMultiFormat = false;
143 
144  // Set up the video and audio...
145  status = SetUpVideo();
146  if (AJA_FAILURE(status))
147  return status;
148  status = mConfig.WithAudio() ? SetUpAudio() : AJA_STATUS_SUCCESS;
149  if (AJA_FAILURE(status))
150  return status;
151 
152  // Set up the circular buffers, and the test pattern buffers...
153  status = SetUpHostBuffers();
154  if (AJA_FAILURE(status))
155  return status;
156  status = SetUpTestPatternBuffers();
157  if (AJA_FAILURE(status))
158  return status;
159 
160  // Set up the device signal routing...
162 
163  // Lastly, prepare my AJATimeCodeBurn instance...
164  if (!mTCBurner.RenderTimeCodeFont (CNTV2DemoCommon::GetAJAPixelFormat(mConfig.fPixelFormat), mFormatDesc.numPixels, mFormatDesc.numLines))
165  {cerr << "## ERROR: RenderTimeCodeFont failed for: " << mFormatDesc << endl; return AJA_STATUS_UNSUPPORTED;}
166 
167  // Ready to go...
168  #if defined(_DEBUG)
169  cerr << mConfig
170  << "Device Description: " << mDevice.GetDescription() << endl
171  << endl;
172  #endif // defined(_DEBUG)
173  return AJA_STATUS_SUCCESS;
174 
175 } // Init
176 
177 
179 {
180  // Configure the device to output the requested video format...
181  if (mConfig.fVideoFormat == NTV2_FORMAT_UNKNOWN)
182  return AJA_STATUS_BAD_PARAM;
183  if (!mDevice.features().CanDoVideoFormat(mConfig.fVideoFormat))
184  { cerr << "## ERROR: '" << mDevice.GetDescription() << "' doesn't support "
185  << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << endl;
186  return AJA_STATUS_UNSUPPORTED;
187  }
188  if (!mDevice.features().CanDoFrameBufferFormat(mConfig.fPixelFormat))
189  { cerr << "## ERROR: '" << mDevice.GetDescription() << "' doesn't support "
190  << ::NTV2FrameBufferFormatString(mConfig.fPixelFormat) << endl;
191  return AJA_STATUS_UNSUPPORTED;
192  }
193  if (::IsRGBFormat(mConfig.fPixelFormat) != mConfig.fDoRGBOnWire && mDevice.features().GetNumCSCs() == 0)
194  { cerr << "## ERROR: '" << mDevice.GetDescription() << "' has no CSCs, and '--pixelFormat' \""
195  << ::NTV2FrameBufferFormatToString(mConfig.fPixelFormat, true) << "\" contradicts '--rgb' setting" << endl;
196  return AJA_STATUS_UNSUPPORTED;
197  }
198 
199  NTV2ChannelSet channels13, frameStores;
200  channels13.insert(NTV2_CHANNEL1); channels13.insert(NTV2_CHANNEL3);
201  if (mConfig.fDoTsiRouting)
202  { // "Tsi" routing requires 2 FrameStores
203  if (channels13.find(mConfig.fOutputChannel) == channels13.end())
204  return AJA_STATUS_BAD_PARAM; // fOutputChannel not Ch1 or Ch3
205  frameStores = ::NTV2MakeChannelSet (mConfig.fOutputChannel, 2); // 2 FrameStores starting at fOutputChannel
206  }
207  else
208  { // "Squares" routing requires 4 FrameStores
209  if (mConfig.fOutputChannel != NTV2_CHANNEL1)
210  return AJA_STATUS_BAD_PARAM; // fOutputChannel not Ch1
211  frameStores = ::NTV2MakeChannelSet (mConfig.fOutputChannel, 4); // 4 FrameStores starting at fOutputChannel
212  }
213 
214  // Keep the raster description handy...
215  mFormatDesc = NTV2FormatDescriptor(mConfig.fVideoFormat, mConfig.fPixelFormat);
216  if (!mFormatDesc.IsValid())
217  return AJA_STATUS_FAIL;
218 
219  // Turn on the FrameStores (to read frame buffer memory and transmit video)...
220  mDevice.EnableChannels (frameStores, /*disableOthers=*/!mConfig.fDoMultiFormat);
221 
222  // This demo requires VANC be disabled...
223  mDevice.SetVANCMode (frameStores, NTV2_VANCMODE_OFF); // VANC is incompatible with 8K/UHD2 formats
224 
225  // Set the FrameStore video format...
226  mDevice.SetVideoFormat (mConfig.fVideoFormat, false, false, mConfig.fOutputChannel);
227  mDevice.SetQuadQuadFrameEnable (true, mConfig.fOutputChannel);
228  mDevice.SetQuadQuadSquaresEnable (!mConfig.fDoTsiRouting, mConfig.fOutputChannel);
229 
230  // Set the frame buffer pixel format for the device FrameStore(s)...
231  mDevice.SetFrameBufferFormat (frameStores, mConfig.fPixelFormat);
232 
233  // The output interrupt is Enabled by default, but on some platforms, you must subscribe to it
234  // in order to be able to wait on its event/semaphore...
236 
237  // Get current per-field maximum Anc buffer size...
240 
241  // Set output clock reference...
243 
244  // At this point, video setup is complete (except for widget signal routing).
245  return AJA_STATUS_SUCCESS;
246 
247 } // SetUpVideo
248 
249 
251 {
252  uint16_t numAudioChannels (mDevice.features().GetMaxAudioChannels());
253  if (numAudioChannels > 8) // If audio system handles more than 8 channels...
254  if (!mDevice.features().CanDo2110()) // ...and SDI (i.e. not ST 2110 IP streaming)...
255  if (NTV2_IS_UHD2_FULL_VIDEO_FORMAT(mConfig.fVideoFormat)) // ...and 8K (narrower HANC only fits 8 audio channels)
256  numAudioChannels = 8; // ...then reduce to 8 audio channels
257 
258  // Use the NTV2AudioSystem that has the same ordinal value as the output FrameStore/Channel...
259  mAudioSystem = ::NTV2ChannelToAudioSystem(mConfig.fOutputChannel);
260 
261  if (mConfig.fNumAudioLinks > 1) // For users that want to send 32 or 64 audio channels on 2 or 4 SDI links
262  switch (mAudioSystem)
263  {
264  default:
265  case NTV2_AUDIOSYSTEM_1:
266  { const UWord numChan(NTV2_IS_QUAD_QUAD_HFR_VIDEO_FORMAT(mConfig.fVideoFormat) ? 4 : 2);
267  const NTV2AudioSystemSet audSystems (::NTV2MakeAudioSystemSet (mAudioSystem, numChan));
268  for (UWord chan(0); chan < numChan; chan++)
269  mDevice.SetSDIOutputAudioSystem (NTV2Channel(chan), NTV2AudioSystem(chan));
270  mDevice.SetNumberAudioChannels (numAudioChannels, audSystems);
271  mDevice.SetAudioBufferSize (NTV2_AUDIO_BUFFER_BIG, audSystems);
272  mDevice.SetAudioLoopBack (NTV2_AUDIO_LOOPBACK_OFF, audSystems);
273  break;
274  }
275  case NTV2_AUDIOSYSTEM_3:
278  break;
279  }
280  else
281  {
282  mDevice.SetSDIOutputAudioSystem (::NTV2MakeChannelSet (NTV2_CHANNEL1, 4), mAudioSystem);
283  mDevice.SetNumberAudioChannels (numAudioChannels, mAudioSystem);
284  mDevice.SetAudioBufferSize (NTV2_AUDIO_BUFFER_BIG, mAudioSystem);
285  mDevice.SetAudioLoopBack (NTV2_AUDIO_LOOPBACK_OFF, mAudioSystem);
286  }
287 
288  if (mConfig.fDoHDMIOutput)
289  {
293  }
294 
295  return AJA_STATUS_SUCCESS;
296 
297 } // SetUpAudio
298 
299 
301 {
302  CNTV2DemoCommon::SetDefaultPageSize(); // Set host-specific page size
303 
304  // Let my circular buffer know when it's time to quit...
305  mFrameDataRing.SetAbortFlag (&mGlobalQuit);
306 
307  // Multi-link audio uses stacked buffers for transferring to the board,
308  // the first byte after the end of the first audio link buffer is the start of the second audio link buffer.
309  const size_t audioBufferSize (gAudMaxSizeBytes * uint32_t(mConfig.fNumAudioLinks));
310 
311  // Allocate and add each in-host NTV2FrameData to my circular buffer member variable...
312  mHostBuffers.reserve(CIRCULAR_BUFFER_SIZE);
313  while (mHostBuffers.size() < CIRCULAR_BUFFER_SIZE)
314  {
315  mHostBuffers.push_back(NTV2FrameData()); // Make a new NTV2FrameData...
316  NTV2FrameData & frameData(mHostBuffers.back()); // ...and get a reference to it
317 
318  // Don't allocate a page-aligned video buffer here.
319  // Instead, the test pattern buffers are used (and re-used) in the consumer thread.
320  // This saves a LOT of memory and time spent copying data with these large 4K/UHD rasters.
321  // NOTE: This differs substantially from the NTV2Player demo, which pre-allocates the ring of video buffers
322  // here, then in its producer thread, copies a fresh, unmodified test pattern raster into the video
323  // buffer, blits timecode into it, then transfers it to the hardware in its consumer thread.
324 
325  // Allocate a page-aligned audio buffer (if transmitting audio)
326  if (mConfig.WithAudio())
327  if (!frameData.fAudioBuffer.Allocate (audioBufferSize, BUFFER_PAGE_ALIGNED))
328  {
329  PLFAIL("Failed to allocate " << xHEX0N(audioBufferSize,8) << "-byte audio buffer");
330  return AJA_STATUS_MEMORY;
331  }
332  if (frameData.fAudioBuffer)
333  {
334  frameData.fAudioBuffer.Fill(ULWord(0));
335  #ifdef NTV2_BUFFER_LOCKING
336  mDevice.DMABufferLock(frameData.fAudioBuffer, /*alsoPreLockSGL*/true);
337  #endif
338  }
339  mFrameDataRing.Add (&frameData);
340  } // for each NTV2FrameData
341  return AJA_STATUS_SUCCESS;
342 
343 } // SetUpHostBuffers
344 
345 
347 {
348  vector<NTV2TestPatternSelect> testPatIDs;
349  testPatIDs.push_back(NTV2_TestPatt_ColorBars100);
350  testPatIDs.push_back(NTV2_TestPatt_ColorBars75);
351  testPatIDs.push_back(NTV2_TestPatt_Ramp);
352  testPatIDs.push_back(NTV2_TestPatt_MultiBurst);
353  testPatIDs.push_back(NTV2_TestPatt_LineSweep);
354  testPatIDs.push_back(NTV2_TestPatt_CheckField);
355  testPatIDs.push_back(NTV2_TestPatt_FlatField);
356  testPatIDs.push_back(NTV2_TestPatt_MultiPattern);
357  testPatIDs.push_back(NTV2_TestPatt_Black);
358  testPatIDs.push_back(NTV2_TestPatt_White);
359  testPatIDs.push_back(NTV2_TestPatt_Border);
360  testPatIDs.push_back(NTV2_TestPatt_LinearRamp);
361  testPatIDs.push_back(NTV2_TestPatt_SlantRamp);
362  testPatIDs.push_back(NTV2_TestPatt_ZonePlate);
363  testPatIDs.push_back(NTV2_TestPatt_ColorQuadrant);
364  testPatIDs.push_back(NTV2_TestPatt_ColorQuadrantBorder);
365 
366  mTestPatRasters.clear();
367  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
368  mTestPatRasters.push_back(NTV2Buffer());
369 
370  if (!mFormatDesc.IsValid())
371  {PLFAIL("Bad format descriptor"); return AJA_STATUS_FAIL;}
372  if (mFormatDesc.IsVANC())
373  {PLFAIL("VANC incompatible with UHD2/8K: " << mFormatDesc); return AJA_STATUS_FAIL;}
374 
375  // Set up one video buffer for each test pattern...
376  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
377  {
378  // Allocate the buffer memory...
379  if (!mTestPatRasters.at(tpNdx).Allocate (mFormatDesc.GetVideoWriteSize(), BUFFER_PAGE_ALIGNED))
380  { PLFAIL("Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << ": "
381  << xHEX0N(mFormatDesc.GetVideoWriteSize(),8) << "-byte page-aligned alloc failed");
382  return AJA_STATUS_MEMORY;
383  }
384 
385  // Fill the buffer with test pattern...
386  NTV2TestPatternGen testPatternGen;
387  if (!testPatternGen.DrawTestPattern (testPatIDs.at(tpNdx), mFormatDesc, mTestPatRasters.at(tpNdx)))
388  {
389  cerr << "## ERROR: DrawTestPattern " << DEC(tpNdx) << " failed: " << mFormatDesc << endl;
390  return AJA_STATUS_FAIL;
391  }
392 
393  #ifdef NTV2_BUFFER_LOCKING
394  // Try to prelock the memory, including its scatter-gather list...
395  if (!mDevice.DMABufferLock(mTestPatRasters.at(tpNdx), /*alsoLockSegmentMap=*/true))
396  PLWARN("Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << ": failed to pre-lock");
397  #endif
398  } // loop for each predefined pattern
399  PLNOTE(DEC(testPatIDs.size()) << " test pattern buffers created, " << DEC(mFormatDesc.GetVideoWriteSize() / 1024 / 1024)
400  << "MB each, " << DEC(mFormatDesc.GetVideoWriteSize() / 1024 / 1024 * testPatIDs.size()) << "MB total");
401  return AJA_STATUS_SUCCESS;
402 
403 } // SetUpTestPatternBuffers
404 
405 
407 {
408  NTV2XptConnections connections; // Routing connections to make
409 
410  if (mConfig.fDoTsiRouting)
411  {
412  if (::IsRGBFormat(mConfig.fPixelFormat))
413  { // RGB on wire requires DualLinkOut widgets
414  if (mConfig.fOutputChannel < NTV2_CHANNEL3)
415  {
420  if (mConfig.fDoHDMIOutput)
422  }
423  else
424  {
429  if (mConfig.fDoHDMIOutput)
431  }
440  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
441  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
442  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
443  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
452  }
453  else
454  {
455  if (mConfig.fOutputChannel < NTV2_CHANNEL3)
456  {
458  {
463  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
464  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
465  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
466  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
475  if (mConfig.fDoHDMIOutput)
477  }
478  else
479  {
484  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
485  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
490  if (mConfig.fDoHDMIOutput)
492  }
493  }
494  else
495  {
497  {
502  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
503  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
504  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
505  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
514  if (mConfig.fDoHDMIOutput)
516  }
517  else
518  {
523  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
524  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
529  if (mConfig.fDoHDMIOutput)
531  }
532  }
533  }
534  }
535  else
536  {
537  if (::IsRGBFormat(mConfig.fPixelFormat))
538  { // RGB on wire requires DualLinkOut widgets
551  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
552  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
553  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
554  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
563  }
564  else
565  {
570  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
571  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
572  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
573  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
582  }
583  }
584  return mDevice.ApplySignalRoute(connections, /*replaceExistingRouting?*/!mConfig.fDoMultiFormat);
585 
586 } // RouteOutputSignal
587 
588 
590 {
591  // Start my consumer and producer threads...
594  return AJA_STATUS_SUCCESS;
595 
596 } // Run
597 
598 
599 
601 // This is where the play thread starts
602 
604 {
605  // Create and start the playout thread...
606  mConsumerThread.Attach (ConsumerThreadStatic, this);
607  mConsumerThread.SetPriority(AJA_ThreadPriority_High);
608  mConsumerThread.Start();
609 
610 } // StartConsumerThread
611 
612 
613 // The playout thread function
614 void NTV2Player8K::ConsumerThreadStatic (AJAThread * pThread, void * pContext) // static
615 { (void) pThread;
616  // Grab the NTV2Player8K instance pointer from the pContext parameter,
617  // then call its PlayFrames method...
618  NTV2Player8K * pApp (reinterpret_cast<NTV2Player8K*>(pContext));
619  if (pApp)
620  pApp->ConsumeFrames();
621 
622 } // ConsumerThreadStatic
623 
624 
626 {
627  ULWord acOptions (AUTOCIRCULATE_WITH_RP188);
628  AUTOCIRCULATE_TRANSFER outputXfer;
629  AUTOCIRCULATE_STATUS outputStatus;
630  AJAAncillaryData * pPkt (AJA_NULL);
631  ULWord goodXfers(0), badXfers(0), prodWaits(0), noRoomWaits(0), startFrm(3);
632  const UWord numACFramesPerChannel(7);
633 
634  // Stop AutoCirculate, just in case someone else left it running...
635  mDevice.AutoCirculateStop(mConfig.fOutputChannel);
636  mDevice.WaitForOutputVerticalInterrupt(mConfig.fOutputChannel, 4); // Let it stop
637  PLNOTE("Thread started");
638 
639  if (pPkt)
640  { // Allocate page-aligned host Anc buffer...
641  uint32_t hdrPktSize (0);
642  if (!outputXfer.acANCBuffer.Allocate(gAncMaxSizeBytes, BUFFER_PAGE_ALIGNED) || !outputXfer.acANCBuffer.Fill(0LL))
643  PLWARN("Anc buffer " << xHEX0N(gAncMaxSizeBytes,8) << "(" << DEC(gAncMaxSizeBytes) << ")-byte allocate failed -- HDR anc insertion disabled");
644  else if (AJA_FAILURE(pPkt->GenerateTransmitData (outputXfer.acANCBuffer, outputXfer.acANCBuffer, hdrPktSize)))
645  {
646  PLWARN("HDR anc insertion disabled -- GenerateTransmitData failed");
647  outputXfer.acANCBuffer.Deallocate();
648  }
649  else
650  acOptions |= AUTOCIRCULATE_WITH_ANC;
651  }
652 #ifdef NTV2_BUFFER_LOCKING
653  if (outputXfer.acANCBuffer)
654  mDevice.DMABufferLock(outputXfer.acANCBuffer, /*alsoLockSGL*/true);
655 #endif
656 
657  // Calculate start & end frame numbers...
658  const UWord startNum (mConfig.fOutputChannel < 2 ? 0 : numACFramesPerChannel); // Ch1: frames 0-6
659  const UWord endNum (mConfig.fOutputChannel < 2 ? numACFramesPerChannel-1 : numACFramesPerChannel*2-1); // Ch5: frames 7-13
660  if (mConfig.fNumAudioLinks > 1)
661  {
664  {
667  }
668  }
669 
670  // Initialize & start AutoCirculate...
671  bool initOK (mDevice.AutoCirculateInitForOutput (mConfig.fOutputChannel, 0, mAudioSystem, acOptions,
672  1 /*numChannels*/, startNum, endNum));
673  if (!initOK)
674  {PLFAIL("AutoCirculateInitForOutput failed"); mGlobalQuit = true;}
675  else
676  { mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outputStatus);
677  startFrm = outputStatus.GetFrameCount() - 1;
678  if (startFrm > 3)
679  startFrm = 3;
680  }
681 
682  while (!mGlobalQuit)
683  {
684  mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outputStatus);
685 
686  // Check if there's room for another frame on the card...
687  if (outputStatus.CanAcceptMoreOutputFrames())
688  {
689  // Device has at least one free frame buffer that can be filled.
690  // Wait for the next frame in our ring to become ready to "consume"...
691  NTV2FrameData * pFrameData (mFrameDataRing.StartConsumeNextBuffer());
692  if (!pFrameData)
693  {prodWaits++; continue;}
694 
695  // Unlike in the NTV2Player demo, I now burn the current timecode into the test pattern buffer that was noted
696  // earlier into this FrameData in my Producer thread. This is done to avoid copying large 8K/UHD2 rasters.
697  const NTV2FrameRate ntv2FrameRate (::GetNTV2FrameRateFromVideoFormat(mConfig.fVideoFormat));
698  const TimecodeFormat tcFormat (CNTV2DemoCommon::NTV2FrameRate2TimecodeFormat(ntv2FrameRate));
699  const CRP188 rp188Info (mCurrentFrame++, 0, 0, 10, tcFormat);
700  NTV2_RP188 tcData;
701  string timeCodeString;
702 
703  rp188Info.GetRP188Reg (tcData);
704  rp188Info.GetRP188Str (timeCodeString);
705  mTCBurner.BurnTimeCode (pFrameData->fVideoBuffer, timeCodeString.c_str(), 80);
706 
707  // Transfer the timecode-burned frame (plus audio) to the device for playout...
708  outputXfer.acVideoBuffer.Set (pFrameData->fVideoBuffer, pFrameData->fVideoBuffer);
709  outputXfer.acAudioBuffer.Set (pFrameData->fAudioBuffer, pFrameData->fNumAudioBytes);
710  outputXfer.SetOutputTimeCode (tcData, ::NTV2ChannelToTimecodeIndex(mConfig.fOutputChannel, /*LTC=*/false, /*F2=*/false));
711  outputXfer.SetOutputTimeCode (tcData, ::NTV2ChannelToTimecodeIndex(mConfig.fOutputChannel, /*LTC=*/true, /*F2=*/false));
712 
713  // Perform the DMA transfer to the device...
714  if (mDevice.AutoCirculateTransfer (mConfig.fOutputChannel, outputXfer))
715  { if (++goodXfers == startFrm)
716  mDevice.AutoCirculateStart(mConfig.fOutputChannel);
717  }
718  else
719  badXfers++;
720 
721  // Signal that the frame has been "consumed"...
722  mFrameDataRing.EndConsumeNextBuffer();
723  continue; // Back to top of while loop
724  }
725 
726  // Wait for one or more buffers to become available on the device, which should occur at next VBI...
727  noRoomWaits++;
729  } // loop til quit signaled
730 
731  // Stop AutoCirculate...
732  mDevice.AutoCirculateStop(mConfig.fOutputChannel);
733  PLNOTE("Thread completed: " << DEC(goodXfers) << " xfers, " << DEC(badXfers) << " failed, "
734  << DEC(prodWaits) << " starves, " << DEC(noRoomWaits) << " VBI waits");
735 
736 } // ConsumeFrames
737 
738 
739 
741 // This is where the producer thread starts
742 
744 {
745  // Create and start the producer thread...
746  mProducerThread.Attach(ProducerThreadStatic, this);
747  mProducerThread.SetPriority(AJA_ThreadPriority_High);
748  mProducerThread.Start();
749 
750 } // StartProducerThread
751 
752 
753 void NTV2Player8K::ProducerThreadStatic (AJAThread * pThread, void * pContext) // static
754 {
755  (void) pThread;
756  NTV2Player8K * pApp (reinterpret_cast<NTV2Player8K*>(pContext));
757  if (pApp)
758  pApp->ProduceFrames();
759 
760 } // ProducerThreadStatic
761 
762 
764 {
765  ULWord freqNdx(0), testPatNdx(0), badTally(0);
766  double timeOfLastSwitch (0.0);
767 
770 
771  PLNOTE("Thread started");
772  while (!mGlobalQuit)
773  {
774  NTV2FrameData * pFrameData (mFrameDataRing.StartProduceNextBuffer());
775  if (!pFrameData)
776  { badTally++; // No frame available!
777  AJATime::Sleep(10); // Wait a bit for the consumer thread to free one up for me...
778  continue; // ...then try again
779  }
780 
781  // Unlike NTV2Player::ProduceFrames, NTV2Player8K::ProduceFrames doesn't touch this frame's video buffer.
782  // Instead, to avoid wasting time copying large 8K/UHD2 rasters, in this thread we simply note which test
783  // pattern buffer is to be modified and subsequently transferred to the hardware. This happens later, in
784  // NTV2Player8K::ConsumeFrames...
785  NTV2Buffer & testPatVidBuffer(mTestPatRasters.at(testPatNdx));
786  pFrameData->fVideoBuffer.Set(testPatVidBuffer.GetHostPointer(), testPatVidBuffer.GetByteCount());
787 
788  // If also playing audio...
789  if (pFrameData->AudioBuffer()) // ...then generate audio tone data for this frame...
790  pFrameData->fNumAudioBytes = AddTone(pFrameData->fAudioBuffer); // ...and remember number of audio bytes to xfer
791 
792  // Every few seconds, change the test pattern and tone frequency...
793  const double currentTime (timeBase.FramesToSeconds(mCurrentFrame++));
794  if (currentTime > timeOfLastSwitch + 4.0)
795  {
796  freqNdx = (freqNdx + 1) % gNumFrequencies;
797  testPatNdx = (testPatNdx + 1) % ULWord(mTestPatRasters.size());
798  mToneFrequency = gFrequencies[freqNdx];
799  timeOfLastSwitch = currentTime;
800  PLINFO("F" << DEC0N(mCurrentFrame,6) << ": tone=" << mToneFrequency << "Hz, pattern='" << tpNames.at(testPatNdx) << "'");
801  } // if time to switch test pattern & tone frequency
802 
803  // Signal that I'm done producing this FrameData, making it immediately available for transfer/playout...
804  mFrameDataRing.EndProduceNextBuffer();
805 
806  } // loop til mGlobalQuit goes true
807  PLNOTE("Thread completed: " << DEC(mCurrentFrame) << " frame(s) produced, " << DEC(badTally) << " failed");
808 
809 } // ProduceFrames
810 
811 
812 uint32_t NTV2Player8K::AddTone (ULWord * audioBuffer)
813 {
816  ULWord numChannels (0);
817 
818  mDevice.GetFrameRate (frameRate, mConfig.fOutputChannel);
819  mDevice.GetAudioRate (audioRate, mAudioSystem);
820  mDevice.GetNumberAudioChannels (numChannels, mAudioSystem);
821 
822  // Since audio on AJA devices use fixed sample rates (typically 48KHz), certain video frame rates will
823  // necessarily result in some frames having more audio samples than others. GetAudioSamplesPerFrame is
824  // called to calculate the correct sample count for the current frame...
825  const ULWord numSamples (::GetAudioSamplesPerFrame (frameRate, audioRate, mCurrentFrame));
826  const double sampleRateHertz (::GetAudioSamplesPerSecond(audioRate));
827 
828  // Unlike NTV2Player::AddTone, NTV2Player8K::AddTone handles multi-link audio:
829  ULWord bytesWritten(0), startSample(mCurrentSample);
830  for (UWord linkNdx(0); linkNdx < mConfig.fNumAudioLinks; linkNdx++)
831  {
832  mCurrentSample = startSample;
833  bytesWritten += ::AddAudioTone (audioBuffer + (bytesWritten/4), // audio buffer to fill
834  mCurrentSample, // which sample for continuing the waveform
835  numSamples, // number of samples to generate
836  sampleRateHertz, // sample rate [Hz]
837  0.5, // amplitude
838  mToneFrequency, // tone frequency [Hz]
839  31, // bits per sample
840  false, // don't byte swap
841  numChannels); // number of audio channels to generate
842  } // for each SDI audio link
843  return bytesWritten;
844 
845 } // AddTone
846 
847 
849 {
850  mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outStatus);
851 }
ULWord GetVideoWriteSize(ULWord inPageSize=4096UL) const
NTV2FrameRate GetNTV2FrameRateFromVideoFormat(const NTV2VideoFormat inVideoFormat)
Definition: ntv2utils.cpp:3630
double FramesToSeconds(int64_t frames) const
Definition: timebase.cpp:205
virtual bool SetTaskMode(const NTV2TaskMode inMode)
Sets the device&#39;s task mode.
#define NTV2_IS_VALID_TASK_MODE(__m__)
static ULWord gAncMaxSizeBytes(NTV2_ANCSIZE_MAX)
The maximum number of bytes of ancillary data that can be transferred for a single field...
NTV2AudioSystem
Used to identify an Audio System on an NTV2 device. See Audio System Operation for more information...
Definition: ntv2enums.h:3901
virtual AJAStatus GenerateTransmitData(uint8_t *pBuffer, const size_t inMaxBytes, uint32_t &outPacketSize)
Generates "raw" ancillary data from my internal ancillary data (playback) – see SDI Anc Buffer Data ...
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 AJAStatus SetUpAudio(void)
Performs all audio setup.
virtual AJAStatus SetUpTestPatternBuffers(void)
Creates my test pattern buffers.
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
#define AUTOCIRCULATE_WITH_MULTILINK_AUDIO3
Use this to AutoCirculate with base audiosystem controlling base AudioSystem + 3. ...
Specifies the device&#39;s internal clock.
Definition: ntv2enums.h:1464
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...
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__)
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
#define NTV2_IS_QUAD_QUAD_HFR_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:830
virtual bool IsDeviceReady(const bool inCheckValid=(0))
static uint64_t GetPid()
Definition: process.cpp:35
#define AJA_FAILURE(_status_)
Definition: types.h:373
#define PLINFO(_xpr_)
Declares the NTV2TestPatternGen class.
virtual bool SubscribeOutputVerticalEvent(const NTV2Channel inChannel=NTV2_CHANNEL1)
Causes me to be notified when an output vertical blanking interrupt is generated for the given output...
Definition: ntv2card.h:2763
virtual bool GetAudioRate(NTV2AudioRate &outRate, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Returns the current NTV2AudioRate for the given Audio System.
Definition: ntv2audio.cpp:227
#define NTV2_IS_UHD2_FULL_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:892
NTV2AudioSystemSet NTV2MakeAudioSystemSet(const NTV2AudioSystem inFirstAudioSystem, const UWord inCount=1)
NTV2Buffer acVideoBuffer
The host video buffer. This field is owned by the client application, and thus is responsible for all...
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...
bool CanAcceptMoreOutputFrames(void) const
virtual void Quit(void)
Gracefully stops me from running.
bool SetOutputTimeCode(const NTV2_RP188 &inTimecode, const NTV2TCIndex inTCIndex=NTV2_TCINDEX_SDI1)
Intended for playout, sets one element of my acOutputTimeCodes member.
Definition: json.hpp:5362
virtual AJAStatus Start()
Definition: thread.cpp:91
This identifies the 3rd Audio System.
Definition: ntv2enums.h:3905
virtual uint32_t AddTone(ULWord *audioBuffer)
Inserts audio tone (based on my current tone frequency) into the given audio buffer.
void EndConsumeNextBuffer(void)
The consumer thread calls this function to signal that it has finished processing the frame it obtain...
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.
virtual bool SetFrameBufferFormat(NTV2Channel inChannel, NTV2FrameBufferFormat inNewFormat, bool inIsAJARetail=(!(0)), NTV2HDRXferChars inXferChars=NTV2_VPID_TC_SDR_TV, NTV2HDRColorimetry inColorimetry=NTV2_VPID_Color_Rec709, NTV2HDRLuminance inLuminance=NTV2_VPID_Luminance_YCbCr)
Sets the frame buffer format for the given FrameStore on the AJA device.
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They&#39;re also commonly use...
Definition: ntv2enums.h:1361
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 AUTOCIRCULATE_WITH_MULTILINK_AUDIO1
Use this to AutoCirculate with base audiosystem controlling base AudioSystem + 1. ...
Declares the AJATimeBase class.
This struct replaces the old RP188_STRUCT.
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:4966
ULWord numPixels
Width – total number of pixels per line.
virtual bool Active()
Definition: thread.cpp:116
bool Fill(const T &inValue)
Fills me with the given scalar value.
virtual bool GetTaskMode(NTV2TaskMode &outMode)
Retrieves the device&#39;s current task mode.
bool WithAudio(void) const
virtual void StartProducerThread(void)
Starts my producer thread.
virtual AJAStatus SetUpVideo(void)
Performs all video setup.
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:3327
static const bool BUFFER_PAGE_ALIGNED((!(0)))
NTV2FrameRate
Identifies a particular video frame rate.
Definition: ntv2enums.h:416
virtual bool DrawTestPattern(const std::string &inTPName, const NTV2FormatDescriptor &inFormatDesc, NTV2Buffer &inBuffer)
Renders the given test pattern or color into a host raster buffer.
virtual bool EnableChannels(const NTV2ChannelSet &inChannels, const bool inDisableOthers=(0))
Enables the given FrameStore(s).
virtual std::string GetDescription(void) const
Definition: ntv2card.cpp:139
UWord fNumAudioLinks
The number of audio systems to control for multi-link audio (4K/8K)
static TimecodeFormat NTV2FrameRate2TimecodeFormat(const NTV2FrameRate inFrameRate)
virtual bool IsOpen(void) const
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
#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 void ProduceFrames(void)
My producer thread that repeatedly produces video frames.
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.
2: OEM (recommended): device configured by client application(s) with some driver involvement...
virtual bool ApplySignalRoute(const CNTV2SignalRouter &inRouter, const bool inReplace=(0))
Applies the given routing table to the AJA device.
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...
#define PLNOTE(_xpr_)
NTV2XptConnections connections
Definition: ntv2vcam.cpp:1011
std::set< NTV2AudioSystem > NTV2AudioSystemSet
A set of distinct NTV2AudioSystem values. New in SDK 16.2.
NTV2VideoFormat fVideoFormat
The video format to use.
std::string NTV2VideoFormatToString(const NTV2VideoFormat inValue, const bool inUseFrameRate=false)
Definition: ntv2utils.cpp:6750
Embeds silence (zeroes) into the data stream.
Definition: ntv2enums.h:2035
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:1473
bool fDoRGBOnWire
If true, produce RGB on the wire; otherwise output YUV.
#define AUTOCIRCULATE_WITH_ANC
Use this to AutoCirculate with ancillary data.
Specifies channel or FrameStore 2 (or the 2nd item).
Definition: ntv2enums.h:1364
virtual void ConsumeFrames(void)
My consumer thread that repeatedly plays frames using AutoCirculate (until quit). ...
Declares the CNTV2DeviceScanner class.
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 UnsubscribeOutputVerticalEvent(const NTV2Channel inChannel)
Unregisters me so I&#39;m no longer notified when an output VBI is signaled on the given output channel...
Definition: ntv2card.h:2819
bool fDoMultiFormat
If true, enable device-sharing; otherwise take exclusive control of device.
static NTV2TestPatternNames getTestPatternNames(void)
bool IsRGBFormat(const NTV2FrameBufferFormat format)
Definition: ntv2utils.cpp:5414
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...
This object specifies the information that will be transferred to or from the AJA device in the CNTV2...
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
#define DEC(__x__)
bool fDoTsiRouting
If true, enable TSI routing; otherwise route for square division (4K/8K)
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:3903
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 ...
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 AJAStatus Attach(AJAThreadFunction *pThreadFunction, void *pUserContext)
Definition: thread.cpp:169
virtual bool RouteOutputSignal(void)
Performs all widget/signal routing for playout.
bool Set(const void *pInUserPointer, const size_t inByteCount)
Sets (or resets) me from a client-supplied address and size.
I am an object that can play out an 8K or UHD2 test pattern (with timecode) to 4 x 12G SDI outputs of...
Definition: ntv2player8k.h:24
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
virtual bool SetSDIOutRGBLevelAConversion(const UWord inOutputSpigot, const bool inEnable)
Enables or disables an RGB-over-3G-level-A conversion at the SDI output widget (assuming the AJA devi...
Identifies the "normal" Field 2 ancillary data region.
Definition: ntv2enums.h:4236
This identifies the 4th Audio System.
Definition: ntv2enums.h:3906
mFormatDesc
Definition: ntv2vcam.cpp:942
static const double gFrequencies[]
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
ULWord GetFrameCount(void) const
This is returned from the CNTV2Card::AutoCirculateGetStatus function.
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
virtual bool SetQuadQuadFrameEnable(const bool inValue, const NTV2Channel inChannel=NTV2_CHANNEL1)
Enables or disables "quad-quad" 8K frame mode on the device.
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1363
virtual AJAStatus Run(void)
Runs me.
virtual bool AutoCirculateStart(const NTV2Channel inChannel, const ULWord64 inStartTime=0)
Starts AutoCirculate streaming for the specified channel that was previously initialized by CNTV2Card...
bool CanDoFrameBufferFormat(const NTV2PixelFormat inPF)
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 playback streaming, designating a contiguous block of frame buf...
#define xHEX0N(__x__, __n__)
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:6940
static AJA_FrameRate GetAJAFrameRate(const NTV2FrameRate inFrameRate)
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:4873
Specifies channel or FrameStore 4 (or the 4th item).
Definition: ntv2enums.h:1366
std::pair< NTV2InputXptID, NTV2OutputXptID > NTV2XptConnection
NTV2ChannelSet NTV2MakeChannelSet(const NTV2Channel inFirstChannel, const UWord inNumChannels=1)
Configures an NTV2Player instance.
bool GetRP188Reg(RP188_STRUCT &outRP188) const
Definition: ntv2rp188.cpp:1241
NTV2AudioRate
Definition: ntv2enums.h:1933
NTV2StringList NTV2TestPatternNames
An ordered sequence of pattern names.
virtual bool SetQuadQuadSquaresEnable(const bool inValue, const NTV2Channel inChannel=NTV2_CHANNEL1)
Enables or disables quad-quad-frame (8K) squares mode on the device.
#define AUTOCIRCULATE_WITH_MULTILINK_AUDIO2
Use this to AutoCirculate with base audiosystem controlling base AudioSystem + 2. ...
static size_t SetDefaultPageSize(void)
virtual ~NTV2Player8K(void)
std::map< NTV2InputXptID, NTV2OutputXptID > NTV2XptConnections
#define PLWARN(_xpr_)
NTV2Buffer acAudioBuffer
The host audio buffer. This field is owned by the client application, and thus is responsible for all...
virtual void StartConsumerThread(void)
Starts my consumer thread.
bool CanDoVideoFormat(const NTV2VideoFormat inVF)
I am the principal class that stores a single SMPTE-291 SDI ancillary data packet OR the digitized co...
virtual void GetACStatus(AUTOCIRCULATE_STATUS &outStatus)
Provides status information about my output (playout) process.
Header file for NTV2Player8K demonstration class.
#define AUTOCIRCULATE_WITH_RP188
Use this to AutoCirculate with RP188.
const char * NTV2FrameBufferFormatString(NTV2FrameBufferFormat fmt)
Definition: ntv2debug.cpp:220
bool GetRP188Str(std::string &sRP188) const
Definition: ntv2rp188.cpp:918
std::string & lower(std::string &str)
Definition: common.cpp:436
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...
NTV2Buffer acANCBuffer
The host ancillary data buffer. This field is owned by the client application, and thus is responsibl...
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.
static const ULWord gNumFrequencies(sizeof(gFrequencies)/sizeof(double))
NTV2Player8K(const PlayerConfig &inConfig)
Constructs me using the given configuration settings.
virtual AJAStatus SetUpHostBuffers(void)
Sets up my host video & audio buffers.
virtual bool SetVANCMode(const NTV2VANCMode inVancMode, const NTV2Channel inChannel=NTV2_CHANNEL1)
Sets the VANC mode for the given FrameStore.
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
bool fDoHDMIOutput
If true, enable HDMI output; otherwise, disable HDMI output.
#define NTV2_ANCSIZE_MAX
This identifies the mode in which there are no VANC lines in the frame buffer.
Definition: ntv2enums.h:3805
virtual AJAStatus Init(void)
Initializes me and prepares me to Run.
Specifies channel or FrameStore 3 (or the 3rd item).
Definition: ntv2enums.h:1365