AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
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"
17 
18 using namespace std;
19 
20 #define NTV2_BUFFER_LOCKING // IMPORTANT FOR 8K: Define this to pre-lock video/audio buffers in kernel
21 
22 
28 static ULWord gAncMaxSizeBytes (NTV2_ANCSIZE_MAX); // Max per-frame anc buffer size, in bytes
29 
38 static const uint32_t gAudMaxSizeBytes (256 * 1024); // Max per-frame audio buffer size, in bytes
39 
40 static const bool BUFFER_PAGE_ALIGNED (true);
41 
42 // Audio tone generator data
43 static const double gFrequencies [] = {250.0, 500.0, 1000.0, 2000.0};
44 static const ULWord gNumFrequencies (sizeof(gFrequencies) / sizeof(double));
45 // Unlike NTV2Player, this demo uses the same waveform amplitude in each audio channel
46 
47 
49  : mConfig (inConfig),
50  mConsumerThread (),
51  mProducerThread (),
52  mDevice (),
53  mDeviceID (DEVICE_ID_INVALID),
54  mSavedTaskMode (NTV2_TASK_MODE_INVALID),
55  mCurrentFrame (0),
56  mCurrentSample (0),
57  mToneFrequency (440.0),
58  mAudioSystem (NTV2_AUDIOSYSTEM_INVALID),
59  mFormatDesc (),
60  mGlobalQuit (false),
61  mTCBurner (),
62  mHostBuffers (),
63  mFrameDataRing (),
64  mTestPatRasters ()
65 {
66 }
67 
68 
70 {
71  // Stop my playout and producer threads, then destroy them...
72  Quit();
73 
74  mDevice.UnsubscribeOutputVerticalEvent(mConfig.fOutputChannel); // Unsubscribe from output VBI event
75 } // destructor
76 
77 
78 void NTV2Player8K::Quit (void)
79 {
80  // Set the global 'quit' flag, and wait for the threads to go inactive...
81  mGlobalQuit = true;
82 
83  while (mProducerThread.Active())
84  AJATime::Sleep(10);
85 
86  while (mConsumerThread.Active())
87  AJATime::Sleep(10);
88 
89 #if defined(NTV2_BUFFER_LOCKING)
90  mDevice.DMABufferUnlockAll();
91 #endif // NTV2_BUFFER_LOCKING
92  if (!mConfig.fDoMultiFormat && mDevice.IsOpen())
93  {
95  if (NTV2_IS_VALID_TASK_MODE(mSavedTaskMode))
96  mDevice.SetTaskMode(mSavedTaskMode); // Restore prior task mode
97  }
98 } // Quit
99 
100 
102 {
103  AJAStatus status (AJA_STATUS_SUCCESS);
104 
105  // Open the device...
107  {cerr << "## ERROR: Device '" << mConfig.fDeviceSpec << "' not found" << endl; return AJA_STATUS_OPEN;}
108  mDeviceID = mDevice.GetDeviceID(); // Keep this ID handy -- it's used frequently
109 
110  if (!mDevice.IsDeviceReady(false))
111  {cerr << "## ERROR: Device '" << mConfig.fDeviceSpec << "' not ready" << endl; return AJA_STATUS_INITIALIZE;}
112  if (!mDevice.features().CanDoPlayback())
113  {cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' is capture-only" << endl; return AJA_STATUS_FEATURE;}
114 
115  const UWord maxNumChannels (mDevice.features().GetNumFrameStores());
116 
117  // Check for an invalid configuration
119  {cerr << "## ERROR: HFR RGB output not supported" << endl; return AJA_STATUS_BAD_PARAM;}
120 
121  // Check for valid channel...
122  if (UWord(mConfig.fOutputChannel) >= maxNumChannels)
123  {
124  cerr << "## ERROR: Cannot use channel '" << DEC(mConfig.fOutputChannel+1) << "' -- device only supports channel 1"
125  << (maxNumChannels > 1 ? string(" thru ") + string(1, char(maxNumChannels+'0')) : "") << endl;
126  return AJA_STATUS_UNSUPPORTED;
127  }
128  if (mConfig.fOutputChannel != NTV2_CHANNEL1 && mConfig.fOutputChannel != NTV2_CHANNEL3)
129  {
130  cerr << "## ERROR: 8K/UHD2 requires Ch1 or Ch3, not Ch" << DEC(mConfig.fOutputChannel) << endl;
131  return AJA_STATUS_BAD_PARAM;
132  }
133 
134  if (!mConfig.fDoMultiFormat)
135  {
136  mDevice.GetTaskMode(mSavedTaskMode); // Save the current task mode
138  return AJA_STATUS_BUSY; // Device is in use by another app -- fail
139  }
140  mDevice.SetTaskMode(NTV2_OEM_TASKS); // Set OEM service level
141 
142  if (mDevice.features().CanDoMultiFormat())
143  mDevice.SetMultiFormatMode(mConfig.fDoMultiFormat);
144  else
145  mConfig.fDoMultiFormat = false;
146 
147  // Set up the video and audio...
148  status = SetUpVideo();
149  if (AJA_FAILURE(status))
150  return status;
151  status = mConfig.WithAudio() ? SetUpAudio() : AJA_STATUS_SUCCESS;
152  if (AJA_FAILURE(status))
153  return status;
154 
155  // Set up the circular buffers, and the test pattern buffers...
156  status = SetUpHostBuffers();
157  if (AJA_FAILURE(status))
158  return status;
159  status = SetUpTestPatternBuffers();
160  if (AJA_FAILURE(status))
161  return status;
162 
163  // Set up the device signal routing...
165 
166  // Lastly, prepare my AJATimeCodeBurn instance...
167  if (!mTCBurner.RenderTimeCodeFont (CNTV2DemoCommon::GetAJAPixelFormat(mConfig.fPixelFormat), mFormatDesc.numPixels, mFormatDesc.numLines))
168  {cerr << "## ERROR: RenderTimeCodeFont failed for: " << mFormatDesc << endl; return AJA_STATUS_UNSUPPORTED;}
169 
170  // Ready to go...
171  #if defined(_DEBUG)
172  cerr << mConfig;
173  if (mDevice.IsRemote())
174  cerr << "Device Description: " << mDevice.GetDescription() << endl;
175  cerr << endl;
176  #endif // defined(_DEBUG)
177  return AJA_STATUS_SUCCESS;
178 
179 } // Init
180 
181 
183 {
184  // Configure the device to output the requested video format...
185  if (mConfig.fVideoFormat == NTV2_FORMAT_UNKNOWN)
186  return AJA_STATUS_BAD_PARAM;
187  if (!mDevice.features().CanDoVideoFormat(mConfig.fVideoFormat))
188  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' doesn't support "
189  << ::NTV2VideoFormatToString(mConfig.fVideoFormat) << endl;
190  return AJA_STATUS_UNSUPPORTED;
191  }
192  if (!mDevice.features().CanDoFrameBufferFormat(mConfig.fPixelFormat))
193  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' doesn't support "
194  << ::NTV2FrameBufferFormatString(mConfig.fPixelFormat) << endl;
195  return AJA_STATUS_UNSUPPORTED;
196  }
197  if (::IsRGBFormat(mConfig.fPixelFormat) != mConfig.fDoRGBOnWire && mDevice.features().GetNumCSCs() == 0)
198  { cerr << "## ERROR: '" << mDevice.GetDisplayName() << "' has no CSCs, and '--pixelFormat' \""
199  << ::NTV2FrameBufferFormatToString(mConfig.fPixelFormat, true) << "\" contradicts '--rgb' setting" << endl;
200  return AJA_STATUS_UNSUPPORTED;
201  }
202 
203  NTV2ChannelSet channels13, frameStores;
204  channels13.insert(NTV2_CHANNEL1); channels13.insert(NTV2_CHANNEL3);
205  if (mConfig.fDoTsiRouting)
206  { // "Tsi" routing requires 2 FrameStores
207  if (channels13.find(mConfig.fOutputChannel) == channels13.end())
208  return AJA_STATUS_BAD_PARAM; // fOutputChannel not Ch1 or Ch3
209  frameStores = ::NTV2MakeChannelSet (mConfig.fOutputChannel, 2); // 2 FrameStores starting at fOutputChannel
210  }
211  else
212  { // "Squares" routing requires 4 FrameStores
213  if (mConfig.fOutputChannel != NTV2_CHANNEL1)
214  return AJA_STATUS_BAD_PARAM; // fOutputChannel not Ch1
215  frameStores = ::NTV2MakeChannelSet (mConfig.fOutputChannel, 4); // 4 FrameStores starting at fOutputChannel
216  }
217 
218  // Keep the raster description handy...
219  mFormatDesc = NTV2FormatDescriptor(mConfig.fVideoFormat, mConfig.fPixelFormat);
220  if (!mFormatDesc.IsValid())
221  return AJA_STATUS_FAIL;
222 
223  // Turn on the FrameStores (to read frame buffer memory and transmit video)...
224  mDevice.EnableChannels (frameStores, /*disableOthers=*/!mConfig.fDoMultiFormat);
225 
226  // This demo requires VANC be disabled...
227  mDevice.SetVANCMode (frameStores, NTV2_VANCMODE_OFF); // VANC is incompatible with 8K/UHD2 formats
228 
229  // Set the FrameStore video format...
230  mDevice.SetVideoFormat (mConfig.fVideoFormat, false, false, mConfig.fOutputChannel);
231  mDevice.SetQuadQuadFrameEnable (true, mConfig.fOutputChannel);
232  mDevice.SetQuadQuadSquaresEnable (!mConfig.fDoTsiRouting, mConfig.fOutputChannel);
233 
234  // Set the frame buffer pixel format for the device FrameStore(s)...
235  mDevice.SetFrameBufferFormat (frameStores, mConfig.fPixelFormat);
236 
237  // The output interrupt is Enabled by default, but on some platforms, you must subscribe to it
238  // in order to be able to wait on its event/semaphore...
240 
241  // Get current per-field maximum Anc buffer size...
244 
245  // Set output clock reference...
247 
248  // At this point, video setup is complete (except for widget signal routing).
249  return AJA_STATUS_SUCCESS;
250 
251 } // SetUpVideo
252 
253 
255 {
256  uint16_t numAudioChannels (mDevice.features().GetMaxAudioChannels());
257  if (numAudioChannels > 8) // If audio system handles more than 8 channels...
258  if (!mDevice.features().CanDo2110()) // ...and SDI (i.e. not ST 2110 IP streaming)...
259  if (NTV2_IS_UHD2_FULL_VIDEO_FORMAT(mConfig.fVideoFormat)) // ...and 8K (narrower HANC only fits 8 audio channels)
260  numAudioChannels = 8; // ...then reduce to 8 audio channels
261 
262  // Use the NTV2AudioSystem that has the same ordinal value as the output FrameStore/Channel...
263  mAudioSystem = ::NTV2ChannelToAudioSystem(mConfig.fOutputChannel);
264 
265  if (mConfig.fNumAudioLinks > 1) // For users that want to send 32 or 64 audio channels on 2 or 4 SDI links
266  switch (mAudioSystem)
267  {
268  default:
269  case NTV2_AUDIOSYSTEM_1:
270  { const UWord numChan(NTV2_IS_QUAD_QUAD_HFR_VIDEO_FORMAT(mConfig.fVideoFormat) ? 4 : 2);
271  const NTV2AudioSystemSet audSystems (::NTV2MakeAudioSystemSet (mAudioSystem, numChan));
272  for (UWord chan(0); chan < numChan; chan++)
273  mDevice.SetSDIOutputAudioSystem (NTV2Channel(chan), NTV2AudioSystem(chan));
274  mDevice.SetNumberAudioChannels (numAudioChannels, audSystems);
275  mDevice.SetAudioBufferSize (NTV2_AUDIO_BUFFER_BIG, audSystems);
276  mDevice.SetAudioLoopBack (NTV2_AUDIO_LOOPBACK_OFF, audSystems);
277  break;
278  }
279  case NTV2_AUDIOSYSTEM_3:
282  break;
283  }
284  else
285  {
286  mDevice.SetSDIOutputAudioSystem (::NTV2MakeChannelSet (NTV2_CHANNEL1, 4), mAudioSystem);
287  mDevice.SetNumberAudioChannels (numAudioChannels, mAudioSystem);
288  mDevice.SetAudioBufferSize (NTV2_AUDIO_BUFFER_BIG, mAudioSystem);
289  mDevice.SetAudioLoopBack (NTV2_AUDIO_LOOPBACK_OFF, mAudioSystem);
290  }
291 
292  if (mConfig.fDoHDMIOutput)
293  {
297  }
298 
299  return AJA_STATUS_SUCCESS;
300 
301 } // SetUpAudio
302 
303 
305 {
306  CNTV2DemoCommon::SetDefaultPageSize(); // Set host-specific page size
307 
308  // Let my circular buffer know when it's time to quit...
309  mFrameDataRing.SetAbortFlag (&mGlobalQuit);
310 
311  // Multi-link audio uses stacked buffers for transferring to the board,
312  // the first byte after the end of the first audio link buffer is the start of the second audio link buffer.
313  const size_t audioBufferSize (gAudMaxSizeBytes * uint32_t(mConfig.fNumAudioLinks));
314 
315  // Allocate and add each in-host NTV2FrameData to my circular buffer member variable...
316  mHostBuffers.reserve(CIRCULAR_BUFFER_SIZE);
317  while (mHostBuffers.size() < CIRCULAR_BUFFER_SIZE)
318  {
319  mHostBuffers.push_back(NTV2FrameData()); // Make a new NTV2FrameData...
320  NTV2FrameData & frameData(mHostBuffers.back()); // ...and get a reference to it
321 
322  // Don't allocate a page-aligned video buffer here.
323  // Instead, the test pattern buffers are used (and re-used) in the consumer thread.
324  // This saves a LOT of memory and time spent copying data with these large 4K/UHD rasters.
325  // NOTE: This differs substantially from the NTV2Player demo, which pre-allocates the ring of video buffers
326  // here, then in its producer thread, copies a fresh, unmodified test pattern raster into the video
327  // buffer, blits timecode into it, then transfers it to the hardware in its consumer thread.
328 
329  // Allocate a page-aligned audio buffer (if transmitting audio)
330  if (mConfig.WithAudio())
331  if (!frameData.fAudioBuffer.Allocate (audioBufferSize, BUFFER_PAGE_ALIGNED))
332  {
333  PLFAIL("Failed to allocate " << xHEX0N(audioBufferSize,8) << "-byte audio buffer");
334  return AJA_STATUS_MEMORY;
335  }
336  if (frameData.fAudioBuffer)
337  {
338  frameData.fAudioBuffer.Fill(ULWord(0));
339  #ifdef NTV2_BUFFER_LOCKING
340  mDevice.DMABufferLock(frameData.fAudioBuffer, /*alsoPreLockSGL*/true);
341  #endif
342  }
343  mFrameDataRing.Add (&frameData);
344  } // for each NTV2FrameData
345  return AJA_STATUS_SUCCESS;
346 
347 } // SetUpHostBuffers
348 
349 
351 {
352  vector<NTV2TestPatternSelect> testPatIDs;
353  testPatIDs.push_back(NTV2_TestPatt_ColorBars100);
354  testPatIDs.push_back(NTV2_TestPatt_ColorBars75);
355  testPatIDs.push_back(NTV2_TestPatt_Ramp);
356  testPatIDs.push_back(NTV2_TestPatt_MultiBurst);
357  testPatIDs.push_back(NTV2_TestPatt_LineSweep);
358  testPatIDs.push_back(NTV2_TestPatt_CheckField);
359  testPatIDs.push_back(NTV2_TestPatt_FlatField);
360  testPatIDs.push_back(NTV2_TestPatt_MultiPattern);
361  testPatIDs.push_back(NTV2_TestPatt_Black);
362  testPatIDs.push_back(NTV2_TestPatt_White);
363  testPatIDs.push_back(NTV2_TestPatt_Border);
364  testPatIDs.push_back(NTV2_TestPatt_LinearRamp);
365  testPatIDs.push_back(NTV2_TestPatt_SlantRamp);
366  testPatIDs.push_back(NTV2_TestPatt_ZonePlate);
367  testPatIDs.push_back(NTV2_TestPatt_ColorQuadrant);
368  testPatIDs.push_back(NTV2_TestPatt_ColorQuadrantBorder);
369 
370  mTestPatRasters.clear();
371  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
372  mTestPatRasters.push_back(NTV2Buffer());
373 
374  if (!mFormatDesc.IsValid())
375  {PLFAIL("Bad format descriptor"); return AJA_STATUS_FAIL;}
376  if (mFormatDesc.IsVANC())
377  {PLFAIL("VANC incompatible with UHD2/8K: " << mFormatDesc); return AJA_STATUS_FAIL;}
378 
379  // Set up one video buffer for each test pattern...
380  for (size_t tpNdx(0); tpNdx < testPatIDs.size(); tpNdx++)
381  {
382  // Allocate the buffer memory...
383  if (!mTestPatRasters.at(tpNdx).Allocate (mFormatDesc.GetVideoWriteSize(), BUFFER_PAGE_ALIGNED))
384  { PLFAIL("Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << ": "
385  << xHEX0N(mFormatDesc.GetVideoWriteSize(),8) << "-byte page-aligned alloc failed");
386  return AJA_STATUS_MEMORY;
387  }
388 
389  // Fill the buffer with test pattern...
390  NTV2TestPatternGen testPatternGen;
391  if (!testPatternGen.DrawTestPattern (testPatIDs.at(tpNdx), mFormatDesc, mTestPatRasters.at(tpNdx)))
392  {
393  cerr << "## ERROR: DrawTestPattern " << DEC(tpNdx) << " failed: " << mFormatDesc << endl;
394  return AJA_STATUS_FAIL;
395  }
396 
397  #ifdef NTV2_BUFFER_LOCKING
398  // Try to prelock the memory, including its scatter-gather list...
399  if (!mDevice.DMABufferLock(mTestPatRasters.at(tpNdx), /*alsoLockSegmentMap=*/true))
400  PLWARN("Test pattern buffer " << DEC(tpNdx+1) << " of " << DEC(testPatIDs.size()) << ": failed to pre-lock");
401  #endif
402  } // loop for each predefined pattern
403  PLNOTE(DEC(testPatIDs.size()) << " test pattern buffers created, " << DEC(mFormatDesc.GetVideoWriteSize() / 1024 / 1024)
404  << "MB each, " << DEC(mFormatDesc.GetVideoWriteSize() / 1024 / 1024 * testPatIDs.size()) << "MB total");
405  return AJA_STATUS_SUCCESS;
406 
407 } // SetUpTestPatternBuffers
408 
409 
411 {
412  NTV2XptConnections connections; // Routing connections to make
413 
414  if (mConfig.fDoTsiRouting)
415  {
416  if (::IsRGBFormat(mConfig.fPixelFormat))
417  { // RGB on wire requires DualLinkOut widgets
418  if (mConfig.fOutputChannel < NTV2_CHANNEL3)
419  {
424  if (mConfig.fDoHDMIOutput)
426  }
427  else
428  {
433  if (mConfig.fDoHDMIOutput)
435  }
444  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
445  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
446  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
447  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
456  }
457  else
458  {
459  if (mConfig.fOutputChannel < NTV2_CHANNEL3)
460  {
462  {
467  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
468  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
469  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
470  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
479  if (mConfig.fDoHDMIOutput)
481  }
482  else
483  {
488  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
489  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
494  if (mConfig.fDoHDMIOutput)
496  }
497  }
498  else
499  {
501  {
506  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
507  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
508  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
509  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
518  if (mConfig.fDoHDMIOutput)
520  }
521  else
522  {
527  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
528  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
533  if (mConfig.fDoHDMIOutput)
535  }
536  }
537  }
538  }
539  else
540  {
541  if (::IsRGBFormat(mConfig.fPixelFormat))
542  { // RGB on wire requires DualLinkOut widgets
555  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
556  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
557  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
558  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
567  }
568  else
569  {
574  mDevice.SetSDITransmitEnable (NTV2_CHANNEL1, true);
575  mDevice.SetSDITransmitEnable (NTV2_CHANNEL2, true);
576  mDevice.SetSDITransmitEnable (NTV2_CHANNEL3, true);
577  mDevice.SetSDITransmitEnable (NTV2_CHANNEL4, true);
586  }
587  }
588  return mDevice.ApplySignalRoute(connections, /*replaceExistingRouting?*/!mConfig.fDoMultiFormat);
589 
590 } // RouteOutputSignal
591 
592 
594 {
595  // Start my consumer and producer threads...
598  return AJA_STATUS_SUCCESS;
599 
600 } // Run
601 
602 
603 
605 // This is where the play thread starts
606 
608 {
609  // Create and start the playout thread...
610  mConsumerThread.Attach (ConsumerThreadStatic, this);
611  mConsumerThread.SetPriority(AJA_ThreadPriority_High);
612  mConsumerThread.Start();
613 
614 } // StartConsumerThread
615 
616 
617 // The playout thread function
618 void NTV2Player8K::ConsumerThreadStatic (AJAThread * pThread, void * pContext) // static
619 { (void) pThread;
620  // Grab the NTV2Player8K instance pointer from the pContext parameter,
621  // then call its PlayFrames method...
622  NTV2Player8K * pApp (reinterpret_cast<NTV2Player8K*>(pContext));
623  if (pApp)
624  pApp->ConsumeFrames();
625 
626 } // ConsumerThreadStatic
627 
628 
630 {
631  ULWord acOptions (AUTOCIRCULATE_WITH_RP188);
632  AUTOCIRCULATE_TRANSFER outputXfer;
633  AUTOCIRCULATE_STATUS outputStatus;
634  AJAAncillaryData * pPkt (AJA_NULL);
635  ULWord goodXfers(0), badXfers(0), prodWaits(0), noRoomWaits(0);
636  const UWord numACFramesPerChannel(7);
637 
638  // Stop AutoCirculate, just in case someone else left it running...
639  mDevice.AutoCirculateStop(mConfig.fOutputChannel);
640  mDevice.WaitForOutputVerticalInterrupt(mConfig.fOutputChannel, 4); // Let it stop
641  PLNOTE("Thread started");
642 
643  if (pPkt)
644  { // Allocate page-aligned host Anc buffer...
645  uint32_t hdrPktSize (0);
646  if (!outputXfer.acANCBuffer.Allocate(gAncMaxSizeBytes, BUFFER_PAGE_ALIGNED) || !outputXfer.acANCBuffer.Fill(0LL))
647  PLWARN("Anc buffer " << xHEX0N(gAncMaxSizeBytes,8) << "(" << DEC(gAncMaxSizeBytes) << ")-byte allocate failed -- HDR anc insertion disabled");
648  else if (AJA_FAILURE(pPkt->GenerateTransmitData (outputXfer.acANCBuffer, outputXfer.acANCBuffer, hdrPktSize)))
649  {
650  PLWARN("HDR anc insertion disabled -- GenerateTransmitData failed");
651  outputXfer.acANCBuffer.Deallocate();
652  }
653  else
654  acOptions |= AUTOCIRCULATE_WITH_ANC;
655  }
656 #ifdef NTV2_BUFFER_LOCKING
657  if (outputXfer.acANCBuffer)
658  mDevice.DMABufferLock(outputXfer.acANCBuffer, /*alsoLockSGL*/true);
659 #endif
660 
661  // Calculate start & end frame numbers...
662  const UWord startNum (mConfig.fOutputChannel < 2 ? 0 : numACFramesPerChannel); // Ch1: frames 0-6
663  const UWord endNum (mConfig.fOutputChannel < 2 ? numACFramesPerChannel-1 : numACFramesPerChannel*2-1); // Ch5: frames 7-13
664  if (mConfig.fNumAudioLinks > 1)
665  {
668  {
671  }
672  }
673 
674  // Initialize & start AutoCirculate...
675  bool initOK (mDevice.AutoCirculateInitForOutput (mConfig.fOutputChannel, 0, mAudioSystem, acOptions,
676  1 /*numChannels*/, startNum, endNum));
677  if (!initOK)
678  {PLFAIL("AutoCirculateInitForOutput failed"); mGlobalQuit = true;}
679 
680  while (!mGlobalQuit)
681  {
682  mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outputStatus);
683 
684  // Check if there's room for another frame on the card...
685  if (outputStatus.CanAcceptMoreOutputFrames())
686  {
687  // Device has at least one free frame buffer that can be filled.
688  // Wait for the next frame in our ring to become ready to "consume"...
689  NTV2FrameData * pFrameData (mFrameDataRing.StartConsumeNextBuffer());
690  if (!pFrameData)
691  {prodWaits++; continue;}
692 
693  // Unlike in the NTV2Player demo, I now burn the current timecode into the test pattern buffer that was noted
694  // earlier into this FrameData in my Producer thread. This is done to avoid copying large 8K/UHD2 rasters.
695  const NTV2FrameRate ntv2FrameRate (::GetNTV2FrameRateFromVideoFormat(mConfig.fVideoFormat));
696  const TimecodeFormat tcFormat (CNTV2DemoCommon::NTV2FrameRate2TimecodeFormat(ntv2FrameRate));
697  const CRP188 rp188Info (mCurrentFrame++, 0, 0, 10, tcFormat);
698  NTV2_RP188 tcData;
699  string timeCodeString;
700 
701  rp188Info.GetRP188Reg (tcData);
702  rp188Info.GetRP188Str (timeCodeString);
703  mTCBurner.BurnTimeCode (pFrameData->fVideoBuffer, timeCodeString.c_str(), 80);
704 
705  // Transfer the timecode-burned frame (plus audio) to the device for playout...
706  outputXfer.acVideoBuffer.Set (pFrameData->fVideoBuffer, pFrameData->fVideoBuffer);
707  outputXfer.acAudioBuffer.Set (pFrameData->fAudioBuffer, pFrameData->fNumAudioBytes);
708  outputXfer.SetOutputTimeCode (tcData, ::NTV2ChannelToTimecodeIndex(mConfig.fOutputChannel, /*LTC=*/false, /*F2=*/false));
709  outputXfer.SetOutputTimeCode (tcData, ::NTV2ChannelToTimecodeIndex(mConfig.fOutputChannel, /*LTC=*/true, /*F2=*/false));
710 
711  // Perform the DMA transfer to the device...
712  if (mDevice.AutoCirculateTransfer (mConfig.fOutputChannel, outputXfer))
713  goodXfers++;
714  else
715  badXfers++;
716 
717  if (goodXfers == 3)
718  mDevice.AutoCirculateStart(mConfig.fOutputChannel);
719 
720  // Signal that the frame has been "consumed"...
721  mFrameDataRing.EndConsumeNextBuffer();
722  continue; // Back to top of while loop
723  }
724 
725  // Wait for one or more buffers to become available on the device, which should occur at next VBI...
726  noRoomWaits++;
728  } // loop til quit signaled
729 
730  // Stop AutoCirculate...
731  mDevice.AutoCirculateStop(mConfig.fOutputChannel);
732  PLNOTE("Thread completed: " << DEC(goodXfers) << " xfers, " << DEC(badXfers) << " failed, "
733  << DEC(prodWaits) << " starves, " << DEC(noRoomWaits) << " VBI waits");
734 
735 } // ConsumeFrames
736 
737 
738 
740 // This is where the producer thread starts
741 
743 {
744  // Create and start the producer thread...
745  mProducerThread.Attach(ProducerThreadStatic, this);
746  mProducerThread.SetPriority(AJA_ThreadPriority_High);
747  mProducerThread.Start();
748 
749 } // StartProducerThread
750 
751 
752 void NTV2Player8K::ProducerThreadStatic (AJAThread * pThread, void * pContext) // static
753 {
754  (void) pThread;
755  NTV2Player8K * pApp (reinterpret_cast<NTV2Player8K*>(pContext));
756  if (pApp)
757  pApp->ProduceFrames();
758 
759 } // ProducerThreadStatic
760 
761 
763 {
764  ULWord freqNdx(0), testPatNdx(0), badTally(0);
765  double timeOfLastSwitch (0.0);
766 
769 
770  PLNOTE("Thread started");
771  while (!mGlobalQuit)
772  {
773  NTV2FrameData * pFrameData (mFrameDataRing.StartProduceNextBuffer());
774  if (!pFrameData)
775  { badTally++; // No frame available!
776  AJATime::Sleep(10); // Wait a bit for the consumer thread to free one up for me...
777  continue; // ...then try again
778  }
779 
780  // Unlike NTV2Player::ProduceFrames, NTV2Player8K::ProduceFrames doesn't touch this frame's video buffer.
781  // Instead, to avoid wasting time copying large 8K/UHD2 rasters, in this thread we simply note which test
782  // pattern buffer is to be modified and subsequently transferred to the hardware. This happens later, in
783  // NTV2Player8K::ConsumeFrames...
784  NTV2Buffer & testPatVidBuffer(mTestPatRasters.at(testPatNdx));
785  pFrameData->fVideoBuffer.Set(testPatVidBuffer.GetHostPointer(), testPatVidBuffer.GetByteCount());
786 
787  // If also playing audio...
788  if (pFrameData->AudioBuffer()) // ...then generate audio tone data for this frame...
789  pFrameData->fNumAudioBytes = AddTone(pFrameData->fAudioBuffer); // ...and remember number of audio bytes to xfer
790 
791  // Every few seconds, change the test pattern and tone frequency...
792  const double currentTime (timeBase.FramesToSeconds(mCurrentFrame++));
793  if (currentTime > timeOfLastSwitch + 4.0)
794  {
795  freqNdx = (freqNdx + 1) % gNumFrequencies;
796  testPatNdx = (testPatNdx + 1) % ULWord(mTestPatRasters.size());
797  mToneFrequency = gFrequencies[freqNdx];
798  timeOfLastSwitch = currentTime;
799  PLINFO("F" << DEC0N(mCurrentFrame,6) << ": tone=" << mToneFrequency << "Hz, pattern='" << tpNames.at(testPatNdx) << "'");
800  } // if time to switch test pattern & tone frequency
801 
802  // Signal that I'm done producing this FrameData, making it immediately available for transfer/playout...
803  mFrameDataRing.EndProduceNextBuffer();
804 
805  } // loop til mGlobalQuit goes true
806  PLNOTE("Thread completed: " << DEC(mCurrentFrame) << " frame(s) produced, " << DEC(badTally) << " failed");
807 
808 } // ProduceFrames
809 
810 
811 uint32_t NTV2Player8K::AddTone (ULWord * audioBuffer)
812 {
815  ULWord numChannels (0);
816 
817  mDevice.GetFrameRate (frameRate, mConfig.fOutputChannel);
818  mDevice.GetAudioRate (audioRate, mAudioSystem);
819  mDevice.GetNumberAudioChannels (numChannels, mAudioSystem);
820 
821  // Since audio on AJA devices use fixed sample rates (typically 48KHz), certain video frame rates will
822  // necessarily result in some frames having more audio samples than others. GetAudioSamplesPerFrame is
823  // called to calculate the correct sample count for the current frame...
824  const ULWord numSamples (::GetAudioSamplesPerFrame (frameRate, audioRate, mCurrentFrame));
825  const double sampleRateHertz (::GetAudioSamplesPerSecond(audioRate));
826 
827  // Unlike NTV2Player::AddTone, NTV2Player8K::AddTone handles multi-link audio:
828  ULWord bytesWritten(0), startSample(mCurrentSample);
829  for (UWord linkNdx(0); linkNdx < mConfig.fNumAudioLinks; linkNdx++)
830  {
831  mCurrentSample = startSample;
832  bytesWritten += ::AddAudioTone (audioBuffer + (bytesWritten/4), // audio buffer to fill
833  mCurrentSample, // which sample for continuing the waveform
834  numSamples, // number of samples to generate
835  sampleRateHertz, // sample rate [Hz]
836  0.5, // amplitude
837  mToneFrequency, // tone frequency [Hz]
838  31, // bits per sample
839  false, // don't byte swap
840  numChannels); // number of audio channels to generate
841  } // for each SDI audio link
842  return bytesWritten;
843 
844 } // AddTone
845 
846 
848 {
849  mDevice.AutoCirculateGetStatus (mConfig.fOutputChannel, outStatus);
850 }
ULWord GetVideoWriteSize(ULWord inPageSize=4096UL) const
NTV2FrameRate GetNTV2FrameRateFromVideoFormat(const NTV2VideoFormat inVideoFormat)
Definition: ntv2utils.cpp:3630
Declares the AJAAncillaryData_HDR_HDR10 class.
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 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:3895
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:300
#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:1459
virtual bool SetReference(const NTV2ReferenceSource inRefSource, const bool inKeepFramePulseSelect=(0))
Sets the device&#39;s clock reference source. See Video Output Clocking & Synchronization for more inform...
virtual bool ReleaseStreamForApplication(ULWord inApplicationType, int32_t inProcessID)
Releases exclusive use of the AJA device for the given process, permitting other processes to acquire...
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:826
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 GetAudioRate(NTV2AudioRate &outRate, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Returns the current NTV2AudioRate for the given Audio System.
Definition: ntv2audio.cpp:226
#define NTV2_IS_UHD2_FULL_VIDEO_FORMAT(__f__)
Definition: ntv2enums.h:888
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.
Declares the AJAAncillaryData_HDR_HLG class.
Definition: json.hpp:5362
virtual AJAStatus Start()
Definition: thread.cpp:91
This identifies the 3rd Audio System.
Definition: ntv2enums.h:3899
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:223
virtual bool AutoCirculateGetStatus(const NTV2Channel inChannel, AUTOCIRCULATE_STATUS &outStatus)
Returns the current AutoCirculate status for the given channel.
virtual bool SetFrameBufferFormat(NTV2Channel inChannel, NTV2FrameBufferFormat inNewFormat, bool inIsAJARetail=(!(0)), NTV2HDRXferChars inXferChars=NTV2_VPID_TC_SDR_TV, NTV2HDRColorimetry inColorimetry=NTV2_VPID_Color_Rec709, NTV2HDRLuminance inLuminance=NTV2_VPID_Luminance_YCbCr)
Sets the frame buffer format for the given FrameStore on the AJA device.
NTV2Channel
These enum values are mostly used to identify a specific widget_framestore. They&#39;re also commonly use...
Definition: ntv2enums.h:1357
virtual class DeviceCapabilities & features(void)
Definition: ntv2card.h:148
virtual bool 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:4962
virtual bool IsRemote(void) const
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:1009
bool Deallocate(void)
Deallocates my user-space storage (if I own it – i.e. from a prior call to Allocate).
static AJA_PixelFormat GetAJAPixelFormat(const NTV2PixelFormat inFormat)
This selects audio channels 1 thru 8.
Definition: ntv2enums.h:3322
static const bool BUFFER_PAGE_ALIGNED((!(0)))
NTV2FrameRate
Identifies a particular video frame rate.
Definition: ntv2enums.h:412
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
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...
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:167
void SetAbortFlag(const bool *pAbortFlag)
Tells me the boolean variable I should monitor such that when it gets set to "true" will cause any th...
virtual std::string GetDisplayName(void)
Answers with this device&#39;s display name.
Definition: ntv2card.cpp:88
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:6746
Embeds silence (zeroes) into the data stream.
Definition: ntv2enums.h:2030
AJA_EXPORT bool RenderTimeCodeFont(AJA_PixelFormat pixelFormat, uint32_t numPixels, uint32_t numLines)
virtual bool DMABufferUnlockAll()
Unlocks all previously-locked buffers used for DMA transfers.
Definition: ntv2dma.cpp:457
Specifies the PTP source on SFP 1.
Definition: ntv2enums.h:1468
bool 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:1360
virtual NTV2DeviceID GetDeviceID(void)
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_)
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:5410
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:249
virtual bool GetNumberAudioChannels(ULWord &outNumChannels, const NTV2AudioSystem inAudioSystem=NTV2_AUDIOSYSTEM_1)
Returns the current number of audio channels being captured or played by a given Audio System on the ...
Definition: ntv2audio.cpp:180
#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:3897
virtual bool WaitForOutputVerticalInterrupt(const NTV2Channel inChannel=NTV2_CHANNEL1, UWord inRepeatCount=1)
Efficiently sleeps the calling thread/process until the next one or more field (interlaced video) or ...
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:4230
This identifies the 4th Audio System.
Definition: ntv2enums.h:3900
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:935
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:1031
uint16_t UWord
Definition: ajatypes.h:221
ULWord GetAudioSamplesPerFrame(const NTV2FrameRate inFrameRate, const NTV2AudioRate inAudioRate, ULWord inCadenceFrame=0, bool inIsSMPTE372Enabled=false)
Returns the number of audio samples for a given video frame rate, audio sample rate, and frame number. This is useful since AJA devices use fixed audio sample rates (typically 48KHz), and some video frame rates will necessarily result in some frames having more audio samples than others.
Definition: ntv2utils.cpp:2889
virtual bool SetQuadQuadFrameEnable(const bool inValue, const NTV2Channel inChannel=NTV2_CHANNEL1)
Enables or disables "quad-quad" 8K frame mode on the device.
Declares the AJAAncillaryData_HDR_SDR class.
Specifies channel or FrameStore 1 (or the first item).
Definition: ntv2enums.h:1359
virtual AJAStatus Run(void)
Runs me.
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 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__)
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:6936
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:4869
Specifies channel or FrameStore 4 (or the 4th item).
Definition: ntv2enums.h:1362
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:1928
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:214
bool GetRP188Str(std::string &sRP188) const
Definition: ntv2rp188.cpp:918
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:146
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:3799
virtual AJAStatus Init(void)
Initializes me and prepares me to Run.
Specifies channel or FrameStore 3 (or the 3rd item).
Definition: ntv2enums.h:1361