AJA NTV2 SDK  17.1.1.1245
NTV2 SDK 17.1.1.1245
ancillarylist.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ancillarylist.h"
9 #include "ancillarydatafactory.h"
10 #include "ajabase/system/debug.h"
12 #include "ajabase/system/atomic.h"
13 #include "ajabase/system/lock.h"
14 #if defined (AJALinux)
15  #include <string.h> // For memcpy
16 #endif // AJALinux
17 #if defined(AJAANCLISTIMPL_VECTOR)
18  #include <algorithm>
19 #endif
20 
21 using namespace std;
22 
23 #define LOGGING_ANCLIST AJADebug::IsActive(AJA_DebugUnit_AJAAncList)
24 #define LOGGING_ANC2110RX AJADebug::IsActive(AJA_DebugUnit_Anc2110Rcv)
25 #define LOGGING_ANC2110TX AJADebug::IsActive(AJA_DebugUnit_Anc2110Xmit)
26 
27 #define LOGMYERROR(__x__) {if (LOGGING_ANCLIST) AJA_sERROR (AJA_DebugUnit_AJAAncList, AJAFUNC << ": " << __x__);}
28 #define LOGMYWARN(__x__) {if (LOGGING_ANCLIST) AJA_sWARNING(AJA_DebugUnit_AJAAncList, AJAFUNC << ": " << __x__);}
29 #define LOGMYNOTE(__x__) {if (LOGGING_ANCLIST) AJA_sNOTICE (AJA_DebugUnit_AJAAncList, AJAFUNC << ": " << __x__);}
30 #define LOGMYINFO(__x__) {if (LOGGING_ANCLIST) AJA_sINFO (AJA_DebugUnit_AJAAncList, AJAFUNC << ": " << __x__);}
31 #define LOGMYDEBUG(__x__) {if (LOGGING_ANCLIST) AJA_sDEBUG (AJA_DebugUnit_AJAAncList, AJAFUNC << ": " << __x__);}
32 
33 #define RCVFAIL(__x__) {if (LOGGING_ANC2110RX) AJA_sERROR (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
34 #define RCVWARN(__x__) {if (LOGGING_ANC2110RX) AJA_sWARNING(AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
35 #define RCVNOTE(__x__) {if (LOGGING_ANC2110RX) AJA_sNOTICE (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
36 #define RCVINFO(__x__) {if (LOGGING_ANC2110RX) AJA_sINFO (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
37 #define RCVDBG(__x__) {if (LOGGING_ANC2110RX) AJA_sDEBUG (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
38 
39 #define XMTFAIL(__x__) {if (LOGGING_ANC2110TX) AJA_sERROR (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
40 #define XMTWARN(__x__) {if (LOGGING_ANC2110TX) AJA_sWARNING(AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
41 #define XMTNOTE(__x__) {if (LOGGING_ANC2110TX) AJA_sNOTICE (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
42 #define XMTINFO(__x__) {if (LOGGING_ANC2110TX) AJA_sINFO (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
43 #define XMTDBG(__x__) {if (LOGGING_ANC2110TX) AJA_sDEBUG (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
44 
45 #if defined(AJAHostIsBigEndian)
46  // Host is BigEndian (BE)
47  #define AJA_ENDIAN_16NtoH(__val__) (__val__)
48  #define AJA_ENDIAN_16HtoN(__val__) (__val__)
49  #define AJA_ENDIAN_32NtoH(__val__) (__val__)
50  #define AJA_ENDIAN_32HtoN(__val__) (__val__)
51  #define AJA_ENDIAN_64NtoH(__val__) (__val__)
52  #define AJA_ENDIAN_64HtoN(__val__) (__val__)
53 #else
54  // Host is LittleEndian (LE)
55  #define AJA_ENDIAN_16NtoH(__val__) AJA_ENDIAN_SWAP16(__val__)
56  #define AJA_ENDIAN_16HtoN(__val__) AJA_ENDIAN_SWAP16(__val__)
57  #define AJA_ENDIAN_32NtoH(__val__) AJA_ENDIAN_SWAP32(__val__)
58  #define AJA_ENDIAN_32HtoN(__val__) AJA_ENDIAN_SWAP32(__val__)
59  #define AJA_ENDIAN_64NtoH(__val__) AJA_ENDIAN_SWAP64(__val__)
60  #define AJA_ENDIAN_64HtoN(__val__) AJA_ENDIAN_SWAP64(__val__)
61 #endif
62 
63 static inline uint32_t ENDIAN_32NtoH(const uint32_t inValue) {return AJA_ENDIAN_32NtoH(inValue);}
64 //static inline uint32_t ENDIAN_32HtoN(const uint32_t inValue) {return AJA_ENDIAN_32HtoN(inValue);}
65 
66 static ostream & PrintULWordsBE (ostream & inOutStream, const ULWordSequence & inData, const size_t inMaxNum = 32)
67 {
68  unsigned numPrinted (0);
69  inOutStream << DECN(inData.size(),3) << " U32s: ";
70  for (ULWordSequenceConstIter iter(inData.begin()); iter != inData.end(); )
71  {
72  inOutStream << HEX0N(ENDIAN_32NtoH(*iter),8);
73  numPrinted++;
74  if (++iter != inData.end())
75  {
76  if (numPrinted > inMaxNum)
77  {inOutStream << "..."; break;}
78  inOutStream << " ";
79  }
80  }
81  return inOutStream;
82 }
83 
84 static string ULWordSequenceToStringBE (const ULWordSequence & inData, const size_t inMaxNum = 32)
85 {
86  ostringstream oss;
87  ::PrintULWordsBE (oss, inData, inMaxNum);
88  return oss.str();
89 }
90 
91 ostream & operator << (ostream & inOutStream, const AJAU32Pkts & inPkts)
92 {
93  unsigned rtpPktNum(0);
94  for (AJAU32PktsConstIter pktIter(inPkts.begin()); pktIter != inPkts.end(); ++pktIter)
95  { ++rtpPktNum;
96  inOutStream << "RTP PKT " << DEC0N(rtpPktNum,3) << ":";
97  ::PrintULWordsBE(inOutStream, *pktIter);
98  inOutStream << endl;
99  } // for each RTP packet
100  return inOutStream;
101 }
102 
103 ostream & operator << (ostream & inOutStream, const AJAAncPktDIDSIDSet & inSet)
104 {
105  for (AJAAncPktDIDSIDSetConstIter it(inSet.begin()); it != inSet.end(); )
106  { inOutStream << xHEX0N(*it,4);
107  if (++it != inSet.end())
108  inOutStream << " ";
109  } // for each DID/SID pair
110  return inOutStream;
111 }
112 
113 
114 
116 
117 
118 static bool gIncludeZeroLengthPackets (false);
119 static uint32_t gExcludedZeroLengthPackets (0);
121 
123 { AJAAutoLock locker(&gGlobalLock);
125 }
126 
128 { AJAAutoLock locker(&gGlobalLock);
130 }
131 
133 { AJAAutoLock locker(&gGlobalLock);
135 }
136 
137 inline void AJAAncillaryList::SetIncludeZeroLengthPackets (const bool inInclude)
138 { AJAAutoLock locker(&gGlobalLock);
139  gIncludeZeroLengthPackets = inInclude;
140 }
141 
142 static inline void BumpZeroLengthPacketCount (void)
143 {
145 }
146 
147 
149 
150 
152  : m_ancList (),
153  m_rcvMultiRTP (true), // By default, handle receiving multiple RTP packets
154  m_xmitMultiRTP (false), // By default, transmit single RTP packet
155  m_ignoreCS (false)
156 {
157  Clear();
164 }
165 
166 
168 {
169  Clear();
170 }
171 
172 
174 {
175  if (this != &inRHS)
176  {
177  m_xmitMultiRTP = inRHS.m_xmitMultiRTP;
178  m_rcvMultiRTP = inRHS.m_rcvMultiRTP;
179  m_ignoreCS = inRHS.m_ignoreCS;
180  Clear();
181  for (AJAAncDataListConstIter it(inRHS.m_ancList.begin()); it != inRHS.m_ancList.end(); ++it)
182  if (*it)
183  AddAncillaryData(*it);
184  }
185  return *this;
186 }
187 
188 
190 {
191  AJAAncillaryData * pAncData(AJA_NULL);
192 
193  if (!m_ancList.empty() && inIndex < m_ancList.size())
194  {
195  AJAAncDataListConstIter it (m_ancList.begin());
196 
197  for (uint32_t i(0); i < inIndex; i++) // Dang, std::list has no random access
198  ++it;
199  pAncData = *it;
200  }
201  return pAncData;
202 }
203 
204 
206 {
207  AJAStatus result = AJA_STATUS_SUCCESS;
208 
209  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
210  {
211  AJAAncillaryData * pAncData = *it;
212  AJAStatus status = pAncData->ParsePayloadData ();
213 
214  // Parse ALL items (even if one fails), but only return success if ALL succeed...
215  if (AJA_FAILURE (status))
216  result = status;
217  }
218  return result;
219 }
220 
221 
223 {
224  uint32_t count = 0;
225 
226  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
227  {
228  AJAAncillaryData * pAncData (*it);
229  AJAAncDataType ancType (pAncData->GetAncillaryDataType());
230 
231  if (matchType == ancType)
232  count++;
233  }
234  return count;
235 }
236 
237 
238 AJAAncillaryData * AJAAncillaryList::GetAncillaryDataWithType (const AJAAncDataType matchType, const uint32_t index) const
239 {
240  AJAAncillaryData * pResult (AJA_NULL);
241  uint32_t count = 0;
242 
243  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
244  {
245  AJAAncillaryData * pAncData (*it);
246  AJAAncDataType ancType (pAncData->GetAncillaryDataType());
247 
248  if (matchType == ancType)
249  {
250  if (index == count)
251  {
252  pResult = pAncData;
253  break;
254  }
255  else
256  count++;
257  }
258  }
259  return pResult;
260 }
261 
262 
263 uint32_t AJAAncillaryList::CountAncillaryDataWithID (const uint8_t DID, const uint8_t SID) const
264 {
265  uint32_t count = 0;
266 
267  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
268  {
269  AJAAncillaryData * pAncData = *it;
270 
271  if (DID == AJAAncillaryDataWildcard_DID || DID == pAncData->GetDID())
272  {
273  if (SID == AJAAncillaryDataWildcard_SID || SID == pAncData->GetSID())
274  count++;
275  }
276  }
277  return count;
278 }
279 
280 
281 AJAAncillaryData * AJAAncillaryList::GetAncillaryDataWithID (const uint8_t inDID, const uint8_t inSID, const uint32_t index) const
282 {
283  AJAAncillaryData * pResult (AJA_NULL);
284  uint32_t count(0);
285 
286  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
287  {
288  if (inDID == AJAAncillaryDataWildcard_DID || inDID == (*it)->GetDID())
289  {
290  if (inSID == AJAAncillaryDataWildcard_SID || inSID == (*it)->GetSID())
291  {
292  if (index == count)
293  {
294  pResult = *it;
295  break;
296  }
297  count++;
298  }
299  }
300  }
301  return pResult;
302 }
303 
305 {
306  AJAAncPktDIDSIDSet result;
307  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
308  {
309  const uint16_t pktDIDSID(ToAJAAncPktDIDSID((*it)->GetDID(), (*it)->GetSID()));
310  if (result.find(pktDIDSID) == result.end())
311  result.insert(pktDIDSID);
312  }
313  return result;
314 }
315 
316 
318 {
319  if (&inPackets == this)
320  return AJA_STATUS_BAD_PARAM; // Cannot append from same list!
321  for (AJAAncDataListConstIter it(inPackets.m_ancList.begin()); it != inPackets.m_ancList.end(); ++it)
322  {
323  const AJAAncillaryData * pSrcPkt (*it);
324  if (!pSrcPkt)
325  return AJA_STATUS_FAIL;
326  AJAAncillaryData * pNewPkt (pSrcPkt->Clone());
327  if (!pNewPkt)
328  return AJA_STATUS_FAIL;
329  m_ancList.push_back(pNewPkt);
330  }
331  return AJA_STATUS_SUCCESS;
332 }
333 
334 
336 {
337  if (!pInAncData)
338  return AJA_STATUS_NULL;
339 
340  // Note: this makes a clone of the incoming AJAAncillaryData object and
341  // saves it in the List. The caller is responsible for deleting the original,
342  // and the List owns the clone.
343  const bool wasEmpty (m_ancList.empty());
344  AJAAncillaryData * pData (pInAncData->Clone());
345  if (!pData)
346  return AJA_STATUS_FAIL;
347 
348  // add it to the list
349  if (pData)
350  m_ancList.push_back(pData);
351 
352  LOGMYDEBUG(DEC(m_ancList.size()) << " packet(s) stored" << (wasEmpty ? " from" : " after appending") << " packet " << pData->AsString(32));
353  return AJA_STATUS_SUCCESS;
354 }
355 
356 
358 {
359  uint32_t numDeleted (0);
360  const uint32_t oldSize (uint32_t(m_ancList.size()));
361  for (AJAAncDataListConstIter it (m_ancList.begin()); it != m_ancList.end(); ++it)
362  {
363  AJAAncillaryData * pAncData(*it);
364  if (pAncData)
365  {
366  delete pAncData;
367  numDeleted++;
368  }
369  }
370 
371  m_ancList.clear();
372  if (oldSize || numDeleted)
373  LOGMYDEBUG(numDeleted << " packet(s) deleted -- list emptied");
374  return AJA_STATUS_SUCCESS;
375 }
376 
377 
379 {
380  if (!pAncData)
381  return AJA_STATUS_NULL;
382 
383 #if defined(AJAANCLISTIMPL_VECTOR)
385  for (it = m_ancList.begin(); it != m_ancList.end(); ++it)
386  if (*it == pAncData)
387  break;
388  if (it == m_ancList.end())
389  {LOGMYERROR("failed to remove packet " << pAncData->AsString(32)); return AJA_STATUS_NOT_FOUND;}
390  m_ancList.erase(it);
391 #else
392  m_ancList.remove(pAncData); // note: there's no feedback as to whether one or more elements existed or not
393  // note: pAncData is NOT deleted!
394 #endif
395  LOGMYDEBUG(DEC(m_ancList.size()) << " packet(s) remain after removing packet " << pAncData->AsString(32));
396  return AJA_STATUS_SUCCESS;
397 }
398 
399 
401 {
402  if (!pAncData)
403  return AJA_STATUS_NULL;
404 
405  AJAStatus status (RemoveAncillaryData(pAncData));
406  if (AJA_SUCCESS(status))
407  delete pAncData;
408  return status;
409 }
410 
411 
412 // Sort Predicates
413 
414 static bool SortByDID (AJAAncillaryData * lhs, AJAAncillaryData * rhs)
415 {
416  return lhs->GetDID() < rhs->GetDID();
417 }
418 
419 
420 static bool SortBySID (AJAAncillaryData * lhs, AJAAncillaryData * rhs)
421 {
422  return lhs->GetSID() < rhs->GetSID();
423 }
424 
426 {
427  const AJAAncDataLoc & locLHS (lhs->GetDataLocation());
428  const AJAAncDataLoc & locRHS (rhs->GetDataLocation());
429  return locLHS < locRHS;
430 }
431 
432 
433 // Sort Methods
434 
436 {
437 #if defined(AJAANCLISTIMPL_VECTOR)
438  std::sort(m_ancList.begin(), m_ancList.end(), SortByDID);
439 #else
440  m_ancList.sort (SortByDID);
441 #endif
442  return AJA_STATUS_SUCCESS;
443 }
444 
445 
447 {
448 #if defined(AJAANCLISTIMPL_VECTOR)
449  std::sort(m_ancList.begin(), m_ancList.end(), SortBySID);
450 #else
451  m_ancList.sort (SortBySID);
452 #endif
453  return AJA_STATUS_SUCCESS;
454 }
455 
457 {
458 #if defined(AJAANCLISTIMPL_VECTOR)
459  std::sort(m_ancList.begin(), m_ancList.end(), SortByLocation);
460 #else
461  m_ancList.sort(SortByLocation);
462 #endif
463  return AJA_STATUS_SUCCESS;
464 }
465 
466 
467 AJAStatus AJAAncillaryList::Compare (const AJAAncillaryList & inCompareList, const bool inIgnoreLocation, const bool inIgnoreChecksum) const
468 {
469  if (inCompareList.CountAncillaryData() != CountAncillaryData())
470  return AJA_STATUS_FAIL;
471  for (uint32_t ndx (0); ndx < CountAncillaryData(); ndx++)
472  {
473  AJAAncillaryData * pPktA (inCompareList.GetAncillaryDataAtIndex(ndx));
475  if (AJA_FAILURE(pPktA->Compare(*pPktB, inIgnoreLocation, inIgnoreChecksum)))
476  return AJA_STATUS_FAIL;
477  } // for each packet
478  return AJA_STATUS_SUCCESS;
479 }
480 
481 
482 string AJAAncillaryList::CompareWithInfo (const AJAAncillaryList & inCompareList, const bool inIgnoreLocation, const bool inIgnoreChecksum) const
483 {
484  ostringstream oss;
485  if (inCompareList.CountAncillaryData() != CountAncillaryData())
486  { oss << "Packet count mismatch: " << DEC(CountAncillaryData()) << " vs " << DEC(inCompareList.CountAncillaryData());
487  return oss.str();
488  }
489 
490  for (uint32_t ndx (0); ndx < CountAncillaryData(); ndx++)
491  {
492  AJAAncillaryData * pPktRHS (inCompareList.GetAncillaryDataAtIndex(ndx));
494  const string info (pPkt->CompareWithInfo(*pPktRHS, inIgnoreLocation, inIgnoreChecksum));
495  if (!info.empty())
496  {
497  oss << "Pkt " << DEC(ndx+1) << " of " << DEC(CountAncillaryData()) << ": " << pPkt->AsString() << " != " << pPktRHS->AsString() << ": " << info;
498  return oss.str();
499  }
500  } // for each packet
501  return string();
502 }
503 
504 
505 bool AJAAncillaryList::CompareWithInfo (vector<string> & outDiffInfo, const AJAAncillaryList & inCompareList, const bool inIgnoreLocation, const bool inIgnoreChecksum) const
506 {
507  outDiffInfo.clear();
508  if (inCompareList.CountAncillaryData() != CountAncillaryData())
509  {
510  ostringstream oss;
511  oss << "Packet count mismatch: " << DEC(CountAncillaryData()) << " vs " << DEC(inCompareList.CountAncillaryData());
512  outDiffInfo.push_back(oss.str());
513  return false; // Miscompared
514  }
515 
516  for (uint32_t ndx(0); ndx < CountAncillaryData(); ndx++)
517  {
518  AJAAncillaryData * pPktRHS (inCompareList.GetAncillaryDataAtIndex(ndx));
520  const string info (pPkt->CompareWithInfo(*pPktRHS, inIgnoreLocation, inIgnoreChecksum));
521  if (!info.empty())
522  {
523  ostringstream oss;
524  oss << "Pkt " << DEC(ndx+1) << " of " << DEC(CountAncillaryData()) << ":" << endl
525  << "LHS " << pPkt->AsString(250) << endl
526  << "RHS " << pPktRHS->AsString(250) << endl
527  << info;
528  outDiffInfo.push_back(oss.str());
529  }
530  } // for each packet
531  return outDiffInfo.empty(); // equal if empty list
532 }
533 
534 
538 
539 // Parse a stream of "raw" ancillary data as collected by an AJAAncExtractorWidget.
540 // Break the stream into separate AJAAncillaryData objects and add them to the list.
541 //
542 AJAStatus AJAAncillaryList::AddReceivedAncillaryData (const NTV2Buffer & inReceivedData, const uint32_t inFrameNum)
543 {
544  AJAStatus status (AJA_STATUS_SUCCESS);
545  if (!inReceivedData)
546  return AJA_STATUS_NULL;
547 
548  AJAAncillaryDataList rawPkts; // Accumulate "analog/raw" packets separately
549  AJAAncillaryData newAncData; // Use this as an uninitialized template
551  int32_t remainingSize (int32_t(inReceivedData.GetByteCount()));
552  const uint8_t * pInputData (inReceivedData);
553  bool bMoreData (true);
554 
555  while (bMoreData)
556  {
557  bool bInsertNew (false); // We'll set this 'true' if/when we find a new Anc packet to insert
558  AJAAncDataType newAncType (AJAAncDataType_Unknown); // We'll set this to the proper type once we know it
559  uint32_t packetSize (0); // This is where the AncillaryData object returns the number of bytes that were "consumed" from the input stream
560 
561  // Reset the AncData object, then load itself from the next GUMP packet...
562  newAncData.Clear();
563  status = newAncData.InitWithReceivedData (pInputData, size_t(remainingSize), defaultLoc, packetSize);
564  if (AJA_FAILURE(status))
565  {
566  // TODO: Someday, let's try to recover and process subsequent packets.
567  break; // NOTE: For now, bail on errors in the GUMP stream
568  }
569  else if (packetSize == 0)
570  break; // Nothing to do
571 
572  // Determine what type of anc data we have, and create an object of the appropriate class...
573  if (newAncData.IsDigital())
574  {
575  // Digital anc packets are fairly easy to categorize: you just have to look at their DID/SID.
576  // Also, they are (by definition) independent packets which become independent AJAAncillaryData objects.
577  newAncType = AJAAncillaryDataFactory::GuessAncillaryDataType(&newAncData);
578  bInsertNew = true; // Add it to the list
579  } // digital anc data
580  else if (newAncData.IsRaw())
581  { // "Analog" packets are trickier...
582  // 1) Digitized analog lines are broken into multiple packets by the hardware,
583  // which need to be recombined into a single AJAAncillaryData object.
584  // 2) It is harder to classify the data type, since there is no single easy-to-read
585  // ID. Instead, we rely on the user to tell us what lines are expected to contain
586  // what kind of data (e.g. "expect line 21 to carry 608 captioning...").
587 
588  // This function used to assume that analog packets always were in succession in the buffer.
589  // This isn't true, however, if packet filtering is disabled. Audio packets can be interspersed
590  // between successive analog packets. We now accumulate analog packets separately in "rawPkts",
591  // then add them all to my "m_ancList" member last.
592 
593  // Look for a pkt in "rawPkts" that has the same location...
594  const uint64_t desiredLocation (newAncData.GetDataLocation().OrdinalValue());
595  AJAAncillaryData * pContinuationPkt (AJA_NULL);
596  for (AJAAncDataListConstIter pRaw(rawPkts.begin()); pRaw != rawPkts.end(); ++pRaw)
597  if ((*pRaw)->GetDataLocation().OrdinalValue() == desiredLocation)
598  { // Found one!
599  // "newAncData" must be a continuation of the "pRaw" pkt.
600  // Simply append the new payload data to it...
601  pContinuationPkt = *pRaw;
602  pContinuationPkt->AppendPayload(newAncData);
603  break;
604  }
605 
606  if (!pContinuationPkt)
607  { // If this is NOT a "continuation" packet, then this is a new analog packet.
608  // See if the user has specified an expected Anc data type that matches the
609  // location of the new data...
610  newAncType = GetAnalogAncillaryDataType(newAncData);
611  bInsertNew = true; // Create the new raw pkt, and add it to "rawPkts" queue (below)
612  }
613  } // analog anc data
614 // else
615 // Anc Coding Unknown???? (ignore it)
616 
617  if (bInsertNew)
618  {
619  // Create an AJAAncillaryData object of the appropriate type, and init it with our raw data...
620  AJAAncillaryData * pData (AJAAncillaryDataFactory::Create (newAncType, &newAncData));
621  if (pData)
622  {
624  if (IsIncludingZeroLengthPackets() || pData->GetDC())
625  {
626  try {
627  if (pData->IsRaw())
628  rawPkts.push_back(pData); // New analog pkts go onto my rawPkts queue
629  else
630  m_ancList.push_back(pData); // New digital pkts are immediately appended to my list
631  } catch(...) {status = AJA_STATUS_FAIL;}
632  }
634  if (inFrameNum && !pData->GetFrameID())
635  pData->SetFrameID(inFrameNum);
636  }
637  else
638  status = AJA_STATUS_FAIL;
639  }
640 
641  remainingSize -= packetSize; // Decrease the remaining data size by the amount we just "consumed"
642  pInputData += packetSize; // Advance the input data pointer by the same amount
643  if (remainingSize <= 0) // All of the input data consumed?
644  bMoreData = false;
645  } // while (bMoreData)
646 
647  if (AJA_SUCCESS(status) && !rawPkts.empty())
648  { // Append accumulated analog/raw packets...
649  while (AJA_SUCCESS(status) && !rawPkts.empty())
650  {
651  try {
652  m_ancList.push_back(rawPkts.back());
653  } catch(...) {status = AJA_STATUS_FAIL;}
654  rawPkts.pop_back();
655  }
656  if (AJA_SUCCESS(status))
657  status = SortListByLocation(); // Re-sort by location
658  }
659 
660  return status;
661 
662 } // AddReceivedAncillaryData
663 
664 // Parse a stream of "raw" ancillary data as collected by an HDMI Aux Extractor.
665 // Break the stream into separate AJAAncillaryData objects and add them to the list.
666 //
668  const uint32_t inFrameNum)
669 {
670  AJAStatus status (AJA_STATUS_SUCCESS);
671  const uint8_t * pRcvData = inReceivedData;
672  const uint32_t dataSize = inReceivedData.GetByteCount();
673  if (!pRcvData || !dataSize)
674  return AJA_STATUS_NULL;
675 
676  // Use this as an uninitialized template...
677  AJAAncillaryData newAncData;
678  int32_t remainingSize (int32_t(dataSize + 0));
679  const uint8_t * pInputData (pRcvData);
680  bool bMoreData (true);
681 
682  while (bMoreData)
683  {
684  uint32_t packetSize (0); // This is where the AncillaryData object returns the number of bytes that were "consumed" from the input stream
685  status = newAncData.InitAuxWithReceivedData (pInputData, size_t(remainingSize), packetSize);
686  if (AJA_FAILURE(status))
687  {
688  // TODO: Someday, try to recover and process subsequent packets.
689  break; // NOTE: For now, bail on errors in the stream
690  }
691  else if (packetSize == 0)
692  break; // Nothing to do
693 
694  // Create an AJAAuxiliaryData object of the appropriate type, and init it with our raw data...
696  if (pData)
697  {
699  if (IsIncludingZeroLengthPackets() || pData->GetDC())
700  {
701  try {m_ancList.push_back(pData);} // Append to my list
702  catch(...) {status = AJA_STATUS_FAIL;}
703  }
705  if (inFrameNum && !pData->GetFrameID())
706  pData->SetFrameID(inFrameNum);
707  }
708  else
709  status = AJA_STATUS_FAIL;
710 
711 
712  remainingSize -= packetSize; // Decrease the remaining data size by the amount we just "consumed"
713  pInputData += packetSize; // Advance the input data pointer by the same amount
714  if (remainingSize <= 0) // All of the input data consumed?
715  bMoreData = false;
716  } // while (bMoreData)
717 
718  return status;
719 
720 } // AddReceivedAncillaryData
721 
722 // Parse a "raw" RTP packet received from hardware (ingest) in network byte order into separate
723 // AJAAncillaryData objects and append them to me. 'inReceivedData' includes the RTP header.
725 {
726  AJAStatus status (AJA_STATUS_SUCCESS);
727  if (inReceivedData.empty())
728  {LOGMYWARN("Empty RTP data vector"); return AJA_STATUS_SUCCESS;}
729 
730 LOGMYDEBUG(::ULWordSequenceToStringBE(inReceivedData) << " (BigEndian)"); // ByteSwap em to make em look right
731 
732  // Crack open the RTP packet header...
733  AJARTPAncPayloadHeader RTPheader;
734  if (!RTPheader.ReadFromULWordVector(inReceivedData))
735  {LOGMYERROR("AJARTPAncPayloadHeader::ReadULWordVector failed, " << DEC(4*inReceivedData.size()) << " header bytes"); return AJA_STATUS_FAIL;}
736  if (RTPheader.IsNULL())
737  {LOGMYWARN("No anc packets added: NULL RTP header: " << RTPheader); return AJA_STATUS_SUCCESS;} // Not an error
738  if (!RTPheader.IsValid())
739  {LOGMYWARN("RTP header invalid: " << RTPheader); return AJA_STATUS_FAIL;}
740 
741  const size_t predictedPayloadSize (RTPheader.GetPayloadLength() / sizeof(uint32_t)); // Payload length (excluding RTP header)
742  const size_t actualPayloadSize (inReceivedData.size() - AJARTPAncPayloadHeader::GetHeaderWordCount());
743  const uint32_t numPackets (RTPheader.GetAncPacketCount());
744  uint32_t pktsAdded (0);
745 
746  // Sanity check the RTP header against inReceivedData...
747  if (actualPayloadSize < predictedPayloadSize)
748  {LOGMYERROR("Expected " << DEC(predictedPayloadSize) << ", but only given " << DEC(actualPayloadSize) << " U32s: " << RTPheader); return AJA_STATUS_BADBUFFERCOUNT;}
749  if (!numPackets)
750  {LOGMYWARN("No Anc packets to append: " << RTPheader); return AJA_STATUS_SUCCESS;}
751  if (!actualPayloadSize)
752  {LOGMYWARN("No payload data yet non-zero packet count: " << RTPheader); return AJA_STATUS_FAIL;}
753 
754 LOGMYDEBUG(RTPheader);
755 
756  // Parse each anc pkt in the RTP pkt...
757  uint16_t u32Ndx (5); // First Anc packet starts at ULWord[5]
758  unsigned pktNum (0);
759  for (; pktNum < numPackets && AJA_SUCCESS(status); pktNum++)
760  {
761  AJAAncillaryData tempPkt;
762  status = tempPkt.InitWithReceivedData(inReceivedData, u32Ndx, IgnoreChecksumErrors());
763  if (AJA_FAILURE(status))
764  continue;
765 
767  AJAAncillaryData * pNewPkt (AJAAncillaryDataFactory::Create (newAncType, tempPkt));
768  if (!pNewPkt)
769  {status = AJA_STATUS_NULL; continue;}
770 
771  pNewPkt->SetBufferFormat(AJAAncBufferFormat_RTP); // Originated in RTP packet
772  pNewPkt->SetFrameID(RTPheader.GetTimeStamp()); // TimeStamp it using RTP timestamp
773  if (IsIncludingZeroLengthPackets() || pNewPkt->GetDC())
774  {
775  try {m_ancList.push_back(pNewPkt); pktsAdded++;} // Append to my list
776  catch(...) {status = AJA_STATUS_FAIL;}
777  }
779  } // for each anc packet
780 
781  if (AJA_FAILURE(status))
782  LOGMYERROR(::AJAStatusToString(status) << ": Failed at pkt[" << DEC(pktNum) << "] of " << DEC(numPackets));
783  if (CountAncillaryData() < numPackets)
784  {LOGMYWARN(DEC(pktsAdded) << " of " << DEC(numPackets) << " anc pkt(s) decoded from RTP pkt");}
785  else
786  LOGMYINFO(DEC(numPackets) << " pkts added from RTP pkt: " << *this);
787  return status;
788 } // AddReceivedAncillaryData
789 
790 
792  const UWordSequence & inPacketWords,
796  0))
797 {
798  AJAStatus status (AJA_STATUS_SUCCESS);
799 
800  if (inPacketWords.size () < 7)
801  return AJA_STATUS_RANGE;
802 // NOTE: Tough call. Decided not to validate the AJAAncDataLoc here:
803 // if (!inLoc.IsValid())
804 // return AJA_STATUS_BAD_PARAM;
805 
806  // Use this as an uninitialized template...
807  UWordSequenceConstIter iter(inPacketWords.begin());
808 
809  // Anc packet must start with 0x000 0x3FF 0x3FF sequence...
810  if (*iter != 0x0000)
811  return AJA_STATUS_FAIL;
812  ++iter;
813  if (*iter != 0x03FF)
814  return AJA_STATUS_FAIL;
815  ++iter;
816  if (*iter != 0x03FF)
817  return AJA_STATUS_FAIL;
818  ++iter; // Now pointing at DID
819 
820  outGumpPkt.reserve (outGumpPkt.size() + inPacketWords.size()); // Expand outGumpPkt's capacity in one step
821  const UByteSequence::size_type dataByte1Ndx (outGumpPkt.size()+1); // Index of byte[1] in outgoing Gump packet
822  outGumpPkt.push_back(0xFF); // [0] First byte always 0xFF
823  outGumpPkt.push_back(0x80); // [1] Location data byte 1: "location valid" bit always set
824  outGumpPkt[dataByte1Ndx] |= (inLoc.GetLineNumber() >> 7) & 0x0F; // [1] Location data byte 1: LS 4 bits == MS 4 bits of 11-bit line number
825  if (inLoc.IsLumaChannel())
826  outGumpPkt[dataByte1Ndx] |= 0x20; // [1] Location data byte 1: set Y/C bit for Y/luma channel
827  if (inLoc.IsHanc())
828  outGumpPkt[dataByte1Ndx] |= 0x10; // [1] Location data byte 1: set H/V bit for HANC
829  outGumpPkt.push_back (inLoc.GetLineNumber() & 0x7F); // [2] Location data byte 2: MSB reserved; LS 7 bits == LS 7 bits of 11-bit line number
830 
831  while (iter != inPacketWords.end())
832  {
833  outGumpPkt.push_back(*iter & 0xFF); // Mask off upper byte
834  ++iter;
835  }
836  return status;
837 }
838 
839 
840 AJAStatus AJAAncillaryList::AddVANCData (const UWordSequence & inPacketWords, const AJAAncDataLoc & inLocation, const uint32_t inFrameNum)
841 {
842  UByteSequence gumpPacketData;
843  AJAStatus status (AppendUWordPacketToGump (gumpPacketData, inPacketWords, inLocation));
844  if (AJA_FAILURE(status))
845  return status;
846 
848  AJAAncillaryData * pData (AJA_NULL);
849  {
850  AJAAncillaryData pkt;
851  status = pkt.InitWithReceivedData (gumpPacketData, inLocation);
852  if (AJA_FAILURE(status))
853  return status;
855 
857  pData = AJAAncillaryDataFactory::Create(newAncType, pkt);
858  if (!pData)
859  return AJA_STATUS_FAIL;
860  }
861 
862  if (IsIncludingZeroLengthPackets() || pData->GetDC())
863  {
864  try {m_ancList.push_back(pData);} // Append to my list, I now own the instance
865  catch(...) {delete pData; return AJA_STATUS_FAIL;}
866 
867  if (inFrameNum && pData->GetDID())
868  pData->SetFrameID(inFrameNum);
869  }
870  else
871  {
873  delete pData; // Don't leak zero-length packets
874  }
875  return AJA_STATUS_SUCCESS;
876 
877 } // AddVANCData
878 
879 
881  const NTV2FormatDesc & inFD,
882  AJAAncillaryList & outPkts,
883  const uint32_t inFrameNum)
884 {
885  outPkts.Clear();
886  if (inFB.IsNULL())
887  {
888  LOGMYERROR("AJA_STATUS_NULL: NULL frame buffer pointer");
889  return AJA_STATUS_NULL;
890  }
891  if (!inFD.IsValid())
892  {
893  LOGMYERROR("AJA_STATUS_BAD_PARAM: bad NTV2FormatDescriptor");
894  return AJA_STATUS_BAD_PARAM;
895  }
896  if (!inFD.IsVANC())
897  {
898  LOGMYERROR("AJA_STATUS_BAD_PARAM: format descriptor has no VANC lines");
899  return AJA_STATUS_BAD_PARAM;
900  }
901 
902  const ULWord vancBytes (inFD.GetTotalRasterBytes() - inFD.GetVisibleRasterBytes());
903  const NTV2PixelFormat fbf (inFD.GetPixelFormat());
904  const bool isSD (NTV2_IS_SD_STANDARD(inFD.GetVideoStandard()));
905  if (inFB.GetByteCount() < vancBytes)
906  {
907  LOGMYERROR("AJA_STATUS_FAIL: " << inFB.GetByteCount() << "-byte frame buffer smaller than " << vancBytes << "-byte VANC region");
908  return AJA_STATUS_FAIL;
909  }
910  if (fbf != NTV2_FBF_10BIT_YCBCR && fbf != NTV2_FBF_8BIT_YCBCR)
911  {
912  LOGMYERROR("AJA_STATUS_UNSUPPORTED: frame buffer format " << ::NTV2FrameBufferFormatToString(fbf) << " not '2vuy' nor 'v210'");
913  return AJA_STATUS_UNSUPPORTED; // Only 'v210' and '2vuy' currently supported
914  }
915 
916  for (ULWord lineOffset (0); lineOffset < inFD.GetFirstActiveLine(); lineOffset++)
917  {
918  UWordSequence uwords;
919  bool isF2 (false);
920  ULWord smpteLineNum (0);
921  unsigned ndx (0);
922  const AJAAncDataLink defaultLink (AJAAncDataLink_A); // This is most common
923 
924  inFD.GetSMPTELineNumber (lineOffset, smpteLineNum, isF2);
925  if (fbf == NTV2_FBF_10BIT_YCBCR)
926  ::UnpackLine_10BitYUVtoUWordSequence (inFD.GetRowAddress(inFB.GetHostAddress(0), lineOffset), inFD, uwords);
927  else if (isSD)
929  uwords, inFD.GetRasterWidth());
930  else
932  uwords, inFD.GetRasterWidth());
933  if (isSD)
934  {
936  UWordSequence ycHOffsets;
937  AJAAncDataLoc loc (defaultLink, AJAAncDataChannel_Both, AJAAncDataSpace_VANC, uint16_t(smpteLineNum));
938 
940  NTV2_ASSERT(ycPackets.size() == ycHOffsets.size());
941 
942  for (AJAAncillaryData::U16Packets::const_iterator it(ycPackets.begin()); it != ycPackets.end(); ++it, ndx++)
943  outPkts.AddVANCData (*it, loc.SetHorizontalOffset(ycHOffsets[ndx]), inFrameNum);
944  }
945  else
946  {
947  AJAAncillaryData::U16Packets yPackets, cPackets;
948  UWordSequence yHOffsets, cHOffsets;
949  AJAAncDataLoc yLoc (defaultLink, AJAAncDataChannel_Y, AJAAncDataSpace_VANC, uint16_t(smpteLineNum));
950  AJAAncDataLoc cLoc (defaultLink, AJAAncDataChannel_C, AJAAncDataSpace_VANC, uint16_t(smpteLineNum));
951  //cerr << endl << "SetFromVANCData: +" << DEC0N(lineOffset,2) << ": "; inFD.PrintSMPTELineNumber(cerr, lineOffset); cerr << ":" << endl << uwords << endl;
954  NTV2_ASSERT(yPackets.size() == yHOffsets.size());
955  NTV2_ASSERT(cPackets.size() == cHOffsets.size());
956 
957  unsigned ndxx(0);
958  for (AJAAncillaryData::U16Packets::const_iterator it(yPackets.begin()); it != yPackets.end(); ++it, ndxx++)
959  outPkts.AddVANCData (*it, yLoc.SetHorizontalOffset(yHOffsets[ndxx]), inFrameNum);
960 
961  ndxx = 0;
962  for (AJAAncillaryData::U16Packets::const_iterator it(cPackets.begin()); it != cPackets.end(); ++it, ndxx++)
963  outPkts.AddVANCData (*it, cLoc.SetHorizontalOffset(cHOffsets[ndxx]), inFrameNum);
964  }
965  } // for each VANC line
966  LOGMYDEBUG("returning " << outPkts);
967  return AJA_STATUS_SUCCESS;
968 }
969 
970 // STATIC
972  AJAAncillaryList & outPackets,
973  const uint32_t inFrameNum)
974 {
975  uint32_t RTPPacketCount (0); // Number of packets encountered
976  const uint32_t origPktCount (outPackets.CountAncillaryData());
977  AJAStatus result (AJA_STATUS_SUCCESS);
978 
979  // Try GUMP first...
980  if (BufferHasGUMPData(inAncBuffer))
981  { // GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP GUMP
982  result = outPackets.AddReceivedAncillaryData (inAncBuffer, inFrameNum);
983  if (result == AJA_STATUS_NULL)
984  result = AJA_STATUS_SUCCESS; // A NULL/empty buffer is not an error
985  } // if GUMP
986  else
987  {
988  // RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP RTP
989  NTV2Buffer ancBuffer (inAncBuffer.GetHostPointer(), inAncBuffer.GetByteCount()); // Don't copy
990  size_t ULWordCount (0); // Size of current RTP packet, including RTP header, in 32-bit words
991  size_t ULWordOffset (0); // Offset to start of current RTP packet, in 32-bit words
992  unsigned retries (0); // Retry count
993  const unsigned MAX_RETRIES (4); // Max number of U32s past the end of an RTP packet to look for another
994 
995  while (ancBuffer && retries++ < MAX_RETRIES)
996  {
998  {
999  ULWordSequence U32s;
1000  AJARTPAncPayloadHeader rtpHeader;
1001 
1002  ++RTPPacketCount; // Increment our packet tally
1003 
1004  // Read the RTP packet header to discover the RTP packet's true length...
1005  if (!rtpHeader.ReadFromBuffer(ancBuffer))
1006  {
1007  RCVWARN("On RTP pkt " << DEC(RTPPacketCount) << ", RTP hdr ReadFromBuffer failed at: " << ancBuffer.AsString(40));
1008  break;
1009  }
1010 
1011  ULWordCount = rtpHeader.GetPayloadLength() / sizeof(uint32_t) // payload size
1012  + AJARTPAncPayloadHeader::GetHeaderWordCount(); // plus RTP header size
1013 
1014  // Read ULWordCount x U32s from ancBuffer...
1015  if (!ancBuffer.GetU32s (U32s, /*U32Offset=*/0, /*maxU32sToGet=*/ULWordCount))
1016  {
1017  RCVFAIL("On RTP pkt " << DEC(RTPPacketCount) << ", GetU32s(" << DEC(ULWordCount) << ") at: " << ancBuffer.AsString(40));
1018  return AJA_STATUS_BADBUFFERSIZE; // Ran off the end?
1019  }
1020 
1021  retries = 0; // Reset our retry counter when we get a good header
1022 
1023  // Process the full RTP packet U32s...
1024  result = outPackets.AddReceivedAncillaryData(U32s);
1025  if (AJA_FAILURE(result))
1026  break; // Done -- failed!
1027 
1028  if (!outPackets.AllowMultiRTPReceive())
1029  break; // Only one RTP packet allowed -- done -- success!
1030  } //
1031  else
1032  ULWordCount = 1; // No RTP header found -- move ahead 1 x U32
1033 
1034  // Move "ancBuffer" forward inside "inAncBuffer" to check for another RTP packet...
1035  ULWordOffset += ULWordCount;
1036  ancBuffer.Set (inAncBuffer.GetHostAddress(ULWord(ULWordOffset * sizeof(uint32_t))), // Increment startAddress
1037  inAncBuffer.GetByteCount() - ULWordOffset * sizeof(uint32_t)); // Decrement byteCount
1038  RCVDBG("Moved buffer " << inAncBuffer << " forward by " << DEC(ULWordCount) << " U32s: " << ancBuffer.AsString(20));
1039  } // loop til no more RTP packets found
1040  } // else RTP
1041 
1042  const uint32_t pktsAdded (outPackets.CountAncillaryData() - origPktCount);
1043  if (AJA_SUCCESS(result))
1044  {LOGMYDEBUG("Success: " << DEC(pktsAdded) << " pkts added");}
1045  else
1046  LOGMYERROR(AJAStatusToString(result) << ": " << DEC(pktsAdded) << " pkts added");
1047  return result;
1048 
1049 } // AddFromDeviceAncBuffer
1050 
1051 // STATIC
1053  AJAAncillaryList & outPackets,
1054  const uint32_t inFrameNum)
1055 {
1056  //uint32_t RTPPacketCount (0); // Number of packets encountered
1057  const uint32_t origPktCount (outPackets.CountAncillaryData());
1058  AJAStatus result (AJA_STATUS_SUCCESS);
1059 
1060 
1061  result = outPackets.AddReceivedAuxiliaryData (inAuxBuffer, inFrameNum);
1062  if (result == AJA_STATUS_NULL)
1063  result = AJA_STATUS_SUCCESS; // A NULL/empty buffer is not an error
1064 
1065  const uint32_t pktsAdded (outPackets.CountAncillaryData() - origPktCount);
1066  if (AJA_SUCCESS(result))
1067  {LOGMYDEBUG("Success: " << DEC(pktsAdded) << " pkts added");}
1068  else
1069  LOGMYERROR(AJAStatusToString(result) << ": " << DEC(pktsAdded) << " pkts added");
1070  return result;
1071 
1072 } // AddFromDeviceAuxBuffer
1073 
1074 
1075 // STATIC
1077  const NTV2Buffer & inF2AncBuffer,
1078  AJAAncillaryList & outPackets,
1079  const uint32_t inFrameNum) // STATIC
1080 {
1081  outPackets.Clear();
1082  AJAStatus resultF1(AJA_STATUS_SUCCESS), resultF2(AJA_STATUS_SUCCESS);
1083  resultF1 = AddFromDeviceAncBuffer(inF1AncBuffer, outPackets, inFrameNum);
1084  if (inF2AncBuffer) //Unnecessary to extract from empty buffer, and prevents 0 Packets debug message.
1085  resultF2 = AddFromDeviceAncBuffer(inF2AncBuffer, outPackets, inFrameNum);
1086  if (AJA_FAILURE(resultF1))
1087  return resultF1;
1088  if (AJA_FAILURE(resultF2))
1089  return resultF2;
1090  return AJA_STATUS_SUCCESS;
1091 }
1092 
1094  const NTV2Buffer & inF2AuxBuffer,
1095  AJAAncillaryList & outPackets,
1096  const uint32_t inFrameNum) // STATIC
1097 {
1098  outPackets.Clear();
1099  AJAStatus resultF1,resultF2;
1100  resultF1 = resultF2 = AJA_STATUS_SUCCESS;
1101  resultF1 = AddFromDeviceAuxBuffer(inF1AuxBuffer, outPackets, inFrameNum);
1102  if (inF2AuxBuffer) //Unnecessary to extract from empty buffer, and prevents 0 Packets debug message.
1103  resultF2 = AddFromDeviceAuxBuffer(inF2AuxBuffer, outPackets, inFrameNum);
1104  if (AJA_FAILURE(resultF1))
1105  return resultF1;
1106  if (AJA_FAILURE(resultF2))
1107  return resultF2;
1108  return AJA_STATUS_SUCCESS;
1109 }
1110 
1111 static const size_t MAX_RTP_PKT_LENGTH_BYTES (0x0000FFFF); // 65535 max
1112 static const size_t MAX_RTP_PKT_LENGTH_WORDS ((MAX_RTP_PKT_LENGTH_BYTES+1) / sizeof(uint32_t) - 1); // 16383 max
1113 static const uint32_t MAX_ANC_PKTS_PER_RTP_PKT (0x000000FF); // 255 max
1114 
1115 
1117  AJAAncPktCounts & outF1AncCounts, AJAAncPktCounts & outF2AncCounts,
1118  const bool inIsProgressive, const uint32_t inF2StartLine)
1119 {
1120  AJAStatus result (AJA_STATUS_SUCCESS);
1121  uint32_t actF1PktCnt (0);
1122  uint32_t actF2PktCnt (0);
1123  uint32_t pktNdx (0);
1124  size_t oldPktLengthWords (0);
1125  unsigned countOverflows (0);
1126  size_t overflowWords (0);
1127 
1128  // Reserve space in AJAU32Pkts vectors...
1129  outF1U32Pkts.reserve(CountAncillaryData()); outF1U32Pkts.clear();
1130  outF2U32Pkts.reserve(CountAncillaryData()); outF2U32Pkts.clear();
1131  outF1AncCounts.clear(); outF2AncCounts.clear();
1132 
1133  ULWordSequence F1U32s, F2U32s;
1134  F1U32s.reserve(MAX_RTP_PKT_LENGTH_WORDS);
1135  if (!inIsProgressive)
1136  F2U32s.reserve(MAX_RTP_PKT_LENGTH_WORDS);
1137  F1U32s.clear(); F2U32s.clear();
1138 
1139  // Generate transmit data for each of my packets...
1140  for (pktNdx = 0; pktNdx < CountAncillaryData(); pktNdx++)
1141  {
1142  AJAAncillaryData * pAncData (GetAncillaryDataAtIndex(pktNdx));
1143  if (!pAncData)
1144  return AJA_STATUS_NULL; // Fail
1145 
1146  AJAAncillaryData & pkt (*pAncData);
1147  if (pkt.GetDataCoding() != AJAAncDataCoding_Digital)
1148  {
1149  LOGMYDEBUG("Skipped Pkt " << DEC(pktNdx+1) << " of " << DEC(CountAncillaryData()) << " -- Analog/Raw");
1150  continue; // Skip analog/raw packets
1151  }
1152 
1153  if (inIsProgressive || pkt.GetLocationLineNumber() < inF2StartLine)
1154  {
1155  if (actF1PktCnt >= MAX_ANC_PKTS_PER_RTP_PKT)
1156  {
1157  countOverflows++;
1158  LOGMYDEBUG("Skipped pkt " << DEC(pktNdx+1) << " of " << DEC(CountAncillaryData()) << ", F1 RTP pkt count overflow: " << pkt.AsString(16));
1159  continue;
1160  }
1161  oldPktLengthWords = F1U32s.size();
1162  result = pkt.GenerateTransmitData(F1U32s);
1163  if (AJA_FAILURE(result))
1164  break; // Bail!
1165  if (F1U32s.size() > MAX_RTP_PKT_LENGTH_WORDS)
1166  {
1167  overflowWords += F1U32s.size() - oldPktLengthWords;
1168  LOGMYDEBUG("Skipped pkt " << DEC(pktNdx+1) << " of " << DEC(CountAncillaryData()) << ": F1 RTP pkt length overflow: " << pkt.AsString(16));
1169  while (F1U32s.size() > oldPktLengthWords)
1170  F1U32s.pop_back();
1171  continue;
1172  }
1173  actF1PktCnt++;
1174  if (AllowMultiRTPTransmit())
1175  { // MULTI RTP PKTS
1176  outF1U32Pkts.push_back(F1U32s); // Append it
1177  outF1AncCounts.push_back(1); // One SMPTE Anc packet per RTP packet
1178  XMTDBG("F1 pkt " << DEC(actF1PktCnt) << ": " << ::ULWordSequenceToStringBE(F1U32s) << " (BigEndian)");
1179  F1U32s.clear(); // Start current pkt over
1180  }
1181  }
1182  else
1183  {
1184  if (actF2PktCnt >= MAX_ANC_PKTS_PER_RTP_PKT)
1185  {
1186  countOverflows++;
1187  LOGMYDEBUG("Skipped pkt " << DEC(pktNdx+1) << " of " << DEC(CountAncillaryData()) << ": F2 RTP pkt count overflow: " << pkt.AsString(16));
1188  continue;
1189  }
1190  oldPktLengthWords = F2U32s.size();
1191  result = pkt.GenerateTransmitData(F2U32s);
1192  if (AJA_FAILURE(result))
1193  break; // Bail!
1194  if (AJA_SUCCESS(result) && F2U32s.size() > MAX_RTP_PKT_LENGTH_WORDS)
1195  {
1196  overflowWords += F2U32s.size() - oldPktLengthWords;
1197  LOGMYDEBUG("Skipped pkt " << DEC(pktNdx+1) << " of " << DEC(CountAncillaryData()) << ": F2 RTP pkt length overflow: " << pkt.AsString(16));
1198  while (F2U32s.size() > oldPktLengthWords)
1199  F2U32s.pop_back();
1200  continue;
1201  }
1202  actF2PktCnt++;
1203  if (AllowMultiRTPTransmit())
1204  { // MULTI RTP PKTS
1205  outF2U32Pkts.push_back(F2U32s); // Append it
1206  outF2AncCounts.push_back(1); // One SMPTE Anc packet per RTP packet
1207  XMTDBG("F2 pkt " << DEC(actF2PktCnt) << ": " << ::ULWordSequenceToStringBE(F2U32s) << " (BigEndian)");
1208  F2U32s.clear(); // Start current pkt over
1209  }
1210  }
1211  } // for each SMPTE Anc packet
1212 
1213  if (AJA_FAILURE(result))
1214  {LOGMYERROR(::AJAStatusToString(result) << ": Pkt " << DEC(pktNdx+1) << " of " << DEC(CountAncillaryData()) << " failed in GenerateTransmitData: " << ::AJAStatusToString(result));}
1215  else if (!AllowMultiRTPTransmit())
1216  { // SINGLE RTP PKT
1217  outF1U32Pkts.push_back(F1U32s); // Append all F1
1218  outF1AncCounts.push_back(uint8_t(actF1PktCnt)); // Total F1 SMPTE Anc packets in this one F1 RTP packet
1219  outF2U32Pkts.push_back(F2U32s); // Append all F2
1220  outF2AncCounts.push_back(uint8_t(actF2PktCnt)); // Total F2 SMPTE Anc packets in this one F2 RTP packet
1221  }
1222  if (overflowWords && countOverflows)
1223  {LOGMYWARN("Overflow: " << DEC(countOverflows) << " pkts skipped, " << DEC(overflowWords) << " U32s dropped");}
1224  else if (overflowWords)
1225  {LOGMYWARN("Data overflow: " << DEC(overflowWords) << " U32s dropped");}
1226  else if (countOverflows)
1227  LOGMYWARN("Packet overflow: " << DEC(countOverflows) << " pkts skipped");
1228  XMTDBG("F1 (Content Only): " << outF1U32Pkts);
1229  XMTDBG("F2 (Content Only): " << outF2U32Pkts);
1230  return result;
1231 } // GetRTPPackets
1232 
1233 
1234 
1238 
1239 
1240 AJAStatus AJAAncillaryList::GetAncillaryDataTransmitSize (const bool bProgressive, const uint32_t f2StartLine, uint32_t & ancSizeF1, uint32_t & ancSizeF2)
1241 {
1242  AJAStatus status (AJA_STATUS_SUCCESS);
1243  uint32_t f1Size (0);
1244  uint32_t f2Size (0);
1245 
1246  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
1247  {
1248  AJAAncillaryData * pAncData (*it);
1249  uint32_t packetSize (0);
1250  status = pAncData->GetRawPacketSize (packetSize);
1251  if (status != AJA_STATUS_SUCCESS)
1252  break;
1253 
1254  if (bProgressive || pAncData->GetLocationLineNumber () < f2StartLine)
1255  f1Size += packetSize;
1256  else
1257  f2Size += packetSize;
1258  }
1259 
1260  ancSizeF1 = f1Size;
1261  ancSizeF2 = f2Size;
1262  return status;
1263 }
1264 
1265 
1266 AJAStatus AJAAncillaryList::GetAncillaryDataTransmitData (const bool bProgressive, const uint32_t f2StartLine, uint8_t * pF1AncData, const uint32_t inMaxF1Data, uint8_t * pF2AncData, const uint32_t inMaxF2Data)
1267 {
1268  NTV2Buffer F1Buffer(pF1AncData, inMaxF1Data), F2Buffer(pF2AncData, inMaxF2Data);
1269  if (!F1Buffer.IsNULL())
1270  NTV2_ASSERT(F1Buffer.IsProvidedByClient());
1271  if (!F2Buffer.IsNULL())
1272  NTV2_ASSERT(F2Buffer.IsProvidedByClient());
1273  return GetTransmitData(F1Buffer, F2Buffer, bProgressive, f2StartLine);
1274 }
1275 
1276 
1278  const bool inIsProgressive, const uint32_t inF2StartLine)
1279 {
1280  AJAStatus status (AJA_STATUS_SUCCESS);
1281  size_t maxF1Data (F1Buffer.GetByteCount());
1282  size_t maxF2Data (F2Buffer.GetByteCount());
1283  uint8_t * pF1AncData (reinterpret_cast<uint8_t*>(F1Buffer.GetHostPointer()));
1284  uint8_t * pF2AncData (reinterpret_cast<uint8_t*>(F2Buffer.GetHostPointer()));
1285 
1286  F1Buffer.Fill(uint64_t(0)); F2Buffer.Fill(uint64_t(0));
1287 
1288  // I need to be in ascending line order...
1290 
1291  // Generate transmit data for each of my packets...
1292  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); ++it)
1293  {
1294  uint32_t pktSize(0);
1295  AJAAncillaryData * pPkt(*it);
1296  if (!pPkt)
1297  {status = AJA_STATUS_NULL; break;} // Fail
1298 
1299  if (inIsProgressive || pPkt->GetLocationLineNumber() < inF2StartLine)
1300  {
1301  if (pF1AncData && maxF1Data)
1302  {
1303  status = pPkt->GenerateTransmitData(pF1AncData, maxF1Data, pktSize);
1304  if (AJA_FAILURE(status))
1305  break;
1306 
1307  pF1AncData += pktSize;
1308  maxF1Data -= pktSize;
1309  }
1310  }
1311  else if (pF2AncData && maxF2Data)
1312  {
1313  status = pPkt->GenerateTransmitData(pF2AncData, maxF2Data, pktSize);
1314  if (AJA_FAILURE(status))
1315  break;
1316 
1317  pF2AncData += pktSize;
1318  maxF2Data -= pktSize;
1319  }
1320  } // for each of my anc packets
1321  return status;
1322 }
1323 
1324 
1326 {
1327  if (inFrameBuffer.IsNULL())
1328  {
1329  LOGMYERROR("AJA_STATUS_NULL: null frame buffer");
1330  return AJA_STATUS_NULL;
1331  }
1332  if (!inFormatDesc.IsValid())
1333  {
1334  LOGMYERROR("AJA_STATUS_BAD_PARAM: Invalid format descriptor");
1335  return AJA_STATUS_BAD_PARAM;
1336  }
1337  if (!inFormatDesc.IsVANC())
1338  {
1339  LOGMYERROR("AJA_STATUS_BAD_PARAM: Not a VANC geometry");
1340  return AJA_STATUS_BAD_PARAM;
1341  }
1342  if (inFormatDesc.GetPixelFormat() != NTV2_FBF_10BIT_YCBCR && inFormatDesc.GetPixelFormat() != NTV2_FBF_8BIT_YCBCR)
1343  {
1344  LOGMYERROR("AJA_STATUS_UNSUPPORTED: unsupported pixel format: " << inFormatDesc);
1345  return AJA_STATUS_UNSUPPORTED;
1346  }
1347  if (!CountAncillaryData())
1348  {
1349  LOGMYWARN("List is empty");
1350  return AJA_STATUS_SUCCESS;
1351  }
1352 
1353  // I need to be in ascending line order...
1355 
1356  // BRUTE-FORCE METHOD -- NOT VERY EFFICIENT
1357  const bool isSD (inFormatDesc.IsSD());
1358  AJAAncillaryList failures, successes;
1359  set <uint16_t> lineOffsetsWritten;
1360 
1361  // For each VANC line...
1362  for (UWord fbLineOffset(0); fbLineOffset < inFormatDesc.GetFirstActiveLine(); fbLineOffset++)
1363  {
1364  ULWord smpteLine (0); bool isF2 (false);
1365  inFormatDesc.GetSMPTELineNumber (fbLineOffset, smpteLine, isF2);
1366 
1367  // Look for non-HANC packets destined for this line...
1368  for (AJAAncDataListConstIter iter(m_ancList.begin()); (iter != m_ancList.end()) && *iter; ++iter)
1369  {
1370  bool muxedOK (false);
1371  AJAAncillaryData & ancData (**iter);
1372  const AJAAncDataLoc & loc (ancData.GetDataLocation());
1373  UWordSequence u16PktComponents;
1374  if (ancData.GetDataCoding() != AJAAncDataCoding_Digital) // Ignore "Raw" or "Analog" or "Unknown" packets
1375  continue;
1376  if (loc.GetDataSpace() != AJAAncDataSpace_VANC) // Ignore "HANC" or "Unknown" packets
1377  {
1378  //LOGMYWARN("Skipping non-VANC packet " << ancData);
1379  continue;
1380  }
1381  if (loc.GetLineNumber() != smpteLine) // Wrong line number
1382  {
1383  //LOGMYWARN("Skipping packet not destined for line " << DEC(smpteLine) << " " << loc);
1384  continue;
1385  }
1386  if (!IS_VALID_AJAAncDataChannel(loc.GetDataChannel())) // Bad data channel
1387  {
1388  LOGMYWARN("Skipped packet with invalid data channel " << loc);
1389  continue;
1390  }
1391 
1392  // For v210 buffers, generate 10-bit packet data and put into u16 vector...
1393  muxedOK = AJA_SUCCESS(ancData.GenerateTransmitData(u16PktComponents));
1394  if (muxedOK)
1395  {
1396  if (inFormatDesc.GetPixelFormat() == NTV2_FBF_8BIT_YCBCR) // 2vuy buffers are simple -- just copy the data
1397  {
1398  uint8_t * pLine (reinterpret_cast<uint8_t*>(inFormatDesc.GetWriteableRowAddress(inFrameBuffer.GetHostPointer(), fbLineOffset)));
1399  if (isSD)
1400  { // SD overwrites both Y & C channels in the frame buffer:
1401  for (unsigned ndx(0); ndx < u16PktComponents.size(); ndx++)
1402  pLine[ndx] = uint8_t(u16PktComponents[ndx] & 0xFF);
1403  }
1404  else
1405  { // HD overwrites only the Y or C channel data in the frame buffer:
1406  unsigned dstNdx(loc.IsLumaChannel() ? 1 : 0);
1407  for (unsigned srcNdx(0); srcNdx < u16PktComponents.size(); srcNdx++)
1408  pLine[dstNdx + 2*srcNdx] = uint8_t(u16PktComponents[srcNdx] & 0x00FF);
1409  }
1410  } // if 2vuy
1411  else
1412  {
1413  if (isSD)
1414  { // For SD, just pack the u16 components into the buffer...
1415  while (u16PktComponents.size() < 12 || u16PktComponents.size() % 12) // YUVComponentsTo10BitYUVPackedBuffer fails if packing fewer than 12 words
1416  u16PktComponents.push_back(0x040); // SMPTE black
1417  muxedOK = ::YUVComponentsTo10BitYUVPackedBuffer (u16PktComponents, inFrameBuffer, inFormatDesc, fbLineOffset);
1418  }
1419  else
1420  { // HD overwrites only the Y or C channel data:
1421  UWordSequence YUV16Line;
1422  unsigned dstNdx (loc.IsLumaChannel() ? 1 : 0);
1423 
1424  // Read original Y+C components from FB...
1425  muxedOK = UnpackLine_10BitYUVtoU16s (YUV16Line, inFrameBuffer, inFormatDesc, fbLineOffset);
1426  //cerr << "WriteVANCData|orig: +" << DEC0N(fbLineOffset,2) << ": "; inFormatDesc.PrintSMPTELineNumber(cerr, fbLineOffset); cerr << ":" << endl << YUV16Line << endl;
1427 
1428  // Patch the Y or C channel...
1429  if (muxedOK)
1430  for (unsigned srcNdx(0); srcNdx < u16PktComponents.size(); srcNdx++)
1431  YUV16Line[dstNdx + 2*srcNdx] = u16PktComponents[srcNdx] & 0x03FF;
1432  //cerr << "WriteVANCData|modi: +" << DEC0N(fbLineOffset,2) << ": "; inFormatDesc.PrintSMPTELineNumber(cerr, fbLineOffset); cerr << ":" << endl << YUV16Line << endl;
1433 
1434  // Repack the patched YUV16 line back into the FB...
1435  if (muxedOK)
1436  {
1437  while (YUV16Line.size() < 12 || YUV16Line.size() % 12) // YUVComponentsTo10BitYUVPackedBuffer fails if packing fewer than 12 words
1438  YUV16Line.push_back(0x040); // SMPTE black
1439  muxedOK = ::YUVComponentsTo10BitYUVPackedBuffer (YUV16Line, inFrameBuffer, inFormatDesc, fbLineOffset);
1440  }
1441  } // else HD
1442  } // else v210
1443  } // if GenerateTransmitData OK
1444 
1445  // TBD: NEED TO TAKE INTO CONSIDERATION loc.GetHorizontalOffset()
1446 
1447  if (muxedOK)
1448  {
1449  lineOffsetsWritten.insert(uint16_t(fbLineOffset)); // Remember which FB line offsets we overwrote
1450  successes.AddAncillaryData(ancData);
1451  }
1452  else
1453  failures.AddAncillaryData(ancData);
1454  } // for each packet
1455  } // for each VANC line
1456 
1457  // Any analog packets?
1458  for (AJAAncDataListConstIter iter(m_ancList.begin()); (iter != m_ancList.end()) && *iter; ++iter)
1459  {
1460  bool success (inFormatDesc.IsSD());
1461  AJAAncillaryData & ancData (**iter);
1462  const AJAAncDataLoc & loc (ancData.GetDataLocation());
1463  ULWord lineOffset (0);
1464  if (!ancData.IsRaw())
1465  continue; // Ignore "Digital" or "Unknown" packets
1466 
1467  if (success)
1468  success = inFormatDesc.GetLineOffsetFromSMPTELine (loc.GetLineNumber(), lineOffset);
1469  if (success && lineOffsetsWritten.find(uint16_t(lineOffset)) != lineOffsetsWritten.end())
1470  success = false; // Line already written -- "analog" data overwrites entire line
1471  if (success)
1472  {
1473  if (inFormatDesc.GetPixelFormat() == NTV2_FBF_8BIT_YCBCR)
1474  ::memcpy(inFormatDesc.GetWriteableRowAddress(inFrameBuffer.GetHostPointer(), lineOffset), ancData.GetPayloadData(), ancData.GetDC()); // '2vuy' -- straight copy
1475  else
1476  {
1477  UWordSequence pktComponentData;
1478  success = AJA_SUCCESS(ancData.GenerateTransmitData(pktComponentData));
1479  if (success)
1480  success = ::YUVComponentsTo10BitYUVPackedBuffer (pktComponentData, inFrameBuffer, inFormatDesc, UWord(lineOffset));
1481  }
1482  }
1483 
1484  if (success)
1485  {
1486  lineOffsetsWritten.insert(uint16_t(lineOffset)); // Remember which FB line offsets we overwrote
1487  successes.AddAncillaryData(ancData);
1488  }
1489  else
1490  failures.AddAncillaryData(ancData);
1491  } // for each Analog packet
1492 
1493  if (failures.CountAncillaryData())
1494  LOGMYWARN("FAILURES: " << failures);
1495  if (successes.CountAncillaryData())
1496  LOGMYDEBUG("SUCCESSES: " << successes);
1497 
1498  // At least one success is considered SUCCESS.
1499  // Zero successes and one or more failures is considered FAIL...
1500  return successes.CountAncillaryData() == 0 && failures.CountAncillaryData() > 0 ? AJA_STATUS_FAIL : AJA_STATUS_SUCCESS;
1501 } // WriteVANCData
1502 
1503 
1504 // STATIC
1505 AJAStatus AJAAncillaryList::WriteRTPPackets (NTV2Buffer & theBuffer, uint32_t & outBytesWritten,
1506  const AJAU32Pkts & inRTPPkts, const AJAAncPktCounts & inAncCounts,
1507  const bool inIsF2, const bool inIsProgressive)
1508 {
1509  const ULWord totPkts (ULWord(inRTPPkts.size()));
1510  const string sFld (inIsF2 ? " F2" : " F1");
1511  const string sPrg (inIsProgressive ? " Prg" : " Int");
1512  ULWord u32offset(0), pktNum(1);
1513 
1514  outBytesWritten = 0;
1515  if (inRTPPkts.size() != inAncCounts.size())
1516  {LOGMYERROR(DEC(inRTPPkts.size()) << " RTP pkt(s) != " << DEC(inAncCounts.size()) << " anc count(s)"); return AJA_STATUS_BAD_PARAM;}
1517 
1518  // For each RTP Packet...
1519  for (AJAU32PktsConstIter RTPPktIter(inRTPPkts.begin()); RTPPktIter != inRTPPkts.end(); pktNum++)
1520  {
1521  AJARTPAncPayloadHeader RTPHeader; // The RTP packet header to be built
1522  ULWordSequence RTPHeaderU32s; // The RTP packet header expressed as a sequence of 5 x U32s
1523  const ULWordSequence & origRTPPkt(*RTPPktIter); // The original RTP packet data contents, a sequence of U32s
1524  const bool isLastRTPPkt (++RTPPktIter == inRTPPkts.end()); // Last RTP packet?
1525  const size_t totalRTPPktBytes(AJARTPAncPayloadHeader::GetHeaderByteCount() // RTP packet size,
1526  + origRTPPkt.size() * sizeof(uint32_t)); // including header, in bytes
1527  ostringstream pktNumInfo;
1528  pktNumInfo << " for RTP pkt " << DEC(pktNum) << " of " << DEC(totPkts);
1529 
1530  // Set the RTP Packet Header's info...
1531  if (inIsProgressive)
1532  RTPHeader.SetProgressive();
1533  else if (inIsF2)
1534  RTPHeader.SetField2();
1535  else
1536  RTPHeader.SetField1();
1537  RTPHeader.SetEndOfFieldOrFrame(isLastRTPPkt);
1538  RTPHeader.SetAncPacketCount(uint8_t(inAncCounts.at(pktNum-1))); // Use provided Anc count
1539  RTPHeader.SetPayloadLength(uint16_t(origRTPPkt.size() * sizeof(uint32_t)));
1540  // Playout: Firmware looks for full RTP pkt bytecount in LS 16 bits of SequenceNumber in RTP header:
1541  RTPHeader.SetSequenceNumber(uint32_t(totalRTPPktBytes) & 0x0000FFFF);
1542 
1543  // Convert RTP header object into 5 x U32s...
1544  RTPHeader.WriteToULWordVector(RTPHeaderU32s, true);
1545  NTV2_ASSERT(RTPHeaderU32s.size() == AJARTPAncPayloadHeader::GetHeaderWordCount());
1546 
1547  // Write RTP header into theBuffer...
1548  if (theBuffer)
1549  {
1550  if (!theBuffer.PutU32s(RTPHeaderU32s, u32offset))
1551  {LOGMYERROR("RTP hdr WriteBuffer failed for buffer " << theBuffer << " at u32offset=" << DEC(u32offset)
1552  << pktNumInfo.str()); return AJA_STATUS_FAIL;}
1553  }
1554  u32offset += ULWord(RTPHeaderU32s.size()); // Move "write head" to just past end of RTP header
1555 
1556  // Write RTP packet contents into theBuffer...
1557  if (theBuffer)
1558  {
1559  if (!theBuffer.PutU32s(origRTPPkt, u32offset))
1560  {LOGMYERROR("PutU32s failed writing " << DEC(origRTPPkt.size()) << " U32s in buffer " << theBuffer << " at u32offset=" << DEC(u32offset)
1561  << pktNumInfo.str()); return AJA_STATUS_FAIL;}
1562  LOGMYDEBUG("PutU32s OK @u32offset=" << xHEX0N(u32offset,4) << ": " << RTPHeader << pktNumInfo.str());
1563  }
1564 
1565  // Move "write head" to just past where this RTP packet's data ended...
1566  u32offset += ULWord(origRTPPkt.size());
1567 
1568  // JeffL: IP Anc inserters expect subsequent RTP packets to start on a 64-bit/8-byte word boundary.
1569  if (u32offset & 1L) // If it's not even...
1570  u32offset++; // ...then make it even!
1571  } // for each RTP packet
1572 
1573  outBytesWritten = u32offset * ULWord(sizeof(uint32_t));
1574  if (theBuffer)
1575  LOGMYDEBUG(DEC(totPkts) << " RTP pkt(s), " << DEC(u32offset) << " U32s (" << DEC(outBytesWritten)
1576  << " bytes) written for" << sFld << sPrg);
1577  return AJA_STATUS_SUCCESS;
1578 }
1579 
1580 
1582  const bool inIsProgressive, const uint32_t inF2StartLine)
1583 {
1584  AJAStatus result (AJA_STATUS_SUCCESS);
1585  AJAU32Pkts F1U32Pkts, F2U32Pkts; // 32-bit network-byte-order data
1586  AJAAncPktCounts F1AncCounts, F2AncCounts; // Per-RTP packet anc packet counts
1587  uint32_t byteCount(0); // Not used
1588 
1589  // I need to be in ascending line order...
1590  F1Buffer.Fill(uint64_t(0)); F2Buffer.Fill(uint64_t(0));
1592 
1593  // Get F1 & F2 xmit RTP U32 words (and SMPTE anc packet counts for each RTP packet)...
1594  result = GetRTPPackets (F1U32Pkts, F2U32Pkts, F1AncCounts, F2AncCounts, inIsProgressive, inF2StartLine);
1595  if (AJA_FAILURE(result))
1596  return result;
1597 
1598  /*
1599  ostringstream oss; oss << "Anc Counts: F1="; for (size_t ndx(0); ndx < F1AncCounts.size(); ndx++) oss << (ndx?"|":"[") << DEC(uint16_t(F1AncCounts.at(ndx)));
1600  oss << "] F2="; for (size_t ndx(0); ndx < F2AncCounts.size(); ndx++) oss << (ndx?"|":"[") << DEC(uint16_t(F2AncCounts.at(ndx))); oss << "]";
1601  XMTDBG(oss.str());
1602  */
1603 
1604  // Write the F1 buffer...
1605  result = WriteRTPPackets (F1Buffer, byteCount, F1U32Pkts, F1AncCounts, /*isF2*/false, inIsProgressive);
1606  if (AJA_FAILURE(result))
1607  return result;
1608 
1609  // Write the F2 buffer...
1610  if (!inIsProgressive)
1611  result = WriteRTPPackets (F2Buffer, byteCount, F2U32Pkts, F2AncCounts, /*isF2*/true, inIsProgressive);
1612 
1613  return result;
1614 
1615 } // GetIPTransmitData
1616 
1617 
1618 AJAStatus AJAAncillaryList::GetIPTransmitDataLength (uint32_t & outF1ByteCount, uint32_t & outF2ByteCount,
1619  const bool inIsProgressive, const uint32_t inF2StartLine)
1620 {
1621  outF1ByteCount = outF2ByteCount = 0;
1622 
1623  // Get F1 & F2 xmit RTP U32 words...
1624  AJAU32Pkts F1U32Pkts, F2U32Pkts; // U32 network-byte-order data
1625  AJAAncPktCounts F1AncCounts, F2AncCounts; // Per-RTP packet anc packet counts
1626  AJAStatus result (GetRTPPackets (F1U32Pkts, F2U32Pkts, F1AncCounts, F2AncCounts, inIsProgressive, inF2StartLine));
1627  if (AJA_FAILURE(result))
1628  return result;
1629 
1630  NTV2Buffer nullBuffer; // An empty buffer tells WriteRTPPackets to just calculate byteCount...
1631  result = WriteRTPPackets (nullBuffer, outF1ByteCount, F1U32Pkts, F1AncCounts, /*isF2*/false, inIsProgressive);
1632  if (AJA_SUCCESS(result) && !inIsProgressive)
1633  result = WriteRTPPackets (nullBuffer, outF2ByteCount, F2U32Pkts, F2AncCounts, /*isF2*/true, inIsProgressive);
1634 
1635  return result;
1636 }
1637 
1638 
1639 ostream & AJAAncillaryList::Print (ostream & inOutStream, const bool inDumpPayload) const
1640 {
1641  unsigned num (0);
1642  inOutStream << DEC(CountAncillaryData()) << " pkts:" << endl;
1643  for (AJAAncDataListConstIter it(m_ancList.begin()); it != m_ancList.end(); )
1644  {
1645  AJAAncillaryData * pPkt(*it);
1646  inOutStream << "Pkt" << DEC0N(++num,3) << ": " << pPkt->AsString(inDumpPayload ? 16 : 0);
1647  if (++it != m_ancList.end())
1648  inOutStream << endl;
1649  }
1650  return inOutStream;
1651 }
1652 
1653 // Copies GUMP from inSrc to outDst buffers, but removes ATC, VPID, EDH, VITC & analog packets
1655 {
1656  if (!inSrc || !outDst)
1657  return false; // Buffers must be valid
1658  if (inSrc.GetByteCount() > outDst.GetByteCount())
1659  return false; // Target buffer must be at least as large as source buffer
1660 
1661  uint8_t * srcPtr = inSrc;
1662  uint8_t * ptr = srcPtr;
1663  size_t srcBufSize = inSrc;
1664  uint8_t * tgtPtr = outDst;
1665  size_t uncopied = 0;
1666 // size_t numStripped = 0;
1667 // size_t bytesRemoved = 0;
1668  const size_t kGUMPHeaderSize(7);
1669 
1670  for (size_t ndx(0); ndx < srcBufSize; )
1671  {
1672  if (ptr[0] == 0xff && (ndx + kGUMPHeaderSize) < srcBufSize)
1673  {
1674  bool bFiltered{false};
1675  const uint8_t payloadSize(ptr[5]);
1676 
1677  if (ptr[1] & 0x40) // "Analog/raw"
1678  bFiltered = true;
1679  else if (ptr[3] == 0x60 && ptr[4] == 0x60 && payloadSize == 16) // ATC
1680  bFiltered = true;
1681  else if (ptr[3] == 0x41 && ptr[4] == 0x01 && payloadSize == 4) // SMPTE 352 - VPID
1682  bFiltered = true;
1683  else if (ptr[3] == 0xF4 && ptr[4] == 0x00 && payloadSize == 16) // RP165 EDH
1684  bFiltered = true;
1685  else // VITC
1686  {
1687  const uint16_t lineNum (uint16_t((ptr[1] & 0x0F) << 7) + uint16_t(ptr[2] & 0x7F));
1688  bFiltered = (ptr[1] & 0x40) && (lineNum == 14 || lineNum == 277);
1689  }
1690 
1691  if (bFiltered)
1692  { // Copy everything that came before filtered content...
1693  if (uncopied)
1694  ::memcpy(tgtPtr, srcPtr, uncopied);
1695 
1696  // Skip srcPtr past the filtered content...
1697  srcPtr += uncopied + payloadSize + kGUMPHeaderSize;
1698  tgtPtr += uncopied;
1699  ndx += payloadSize + kGUMPHeaderSize;
1700  ptr = srcPtr;
1701  uncopied = 0;
1702 // numStripped++; bytesRemoved += size_t(payloadSize) + kGUMPHeaderSize;
1703  }
1704  else
1705  {
1706  ptr += payloadSize + kGUMPHeaderSize;
1707  ndx += payloadSize + kGUMPHeaderSize;
1708  uncopied += payloadSize + kGUMPHeaderSize;
1709  }
1710  }
1711  else
1712  {ptr++; ndx++; uncopied++;}
1713  } // for each byte in source buffer
1714 
1715  if (uncopied) // Any uncopied remainder?
1716  ::memcpy(tgtPtr, srcPtr, uncopied); // Copy last uncopied bytes
1717  // cout << DEC(numStripped) << " pkts removed, " << DEC(bytesRemoved) << " bytes removed" << endl;
1718  return true;
1719 } // StripNativeInserterGUMPPackets
1720 
1721 
1725 
1728 
1729 
1731 {
1733  gAnalogTypeMap.clear();
1734  return AJA_STATUS_SUCCESS;
1735 }
1736 
1737 
1739 {
1741  gAnalogTypeMap = inMap;
1742  return AJA_STATUS_SUCCESS;
1743 }
1744 
1745 
1747 {
1749  outMap = gAnalogTypeMap;
1750  return AJA_STATUS_SUCCESS;
1751 }
1752 
1753 
1755 {
1757  gAnalogTypeMap.erase(inLineNum); // In case someone has already set this line
1758  if (inAncType == AJAAncDataType_Unknown)
1759  return AJA_STATUS_SUCCESS; // A non-entry is the same as AJAAncDataType_Unknown
1760  else if (IS_VALID_AJAAncDataType(inAncType))
1761  gAnalogTypeMap[inLineNum] = inAncType;
1762  else
1763  return AJA_STATUS_BAD_PARAM;
1764  return AJA_STATUS_SUCCESS;
1765 }
1766 
1767 
1769 {
1772  if (!gAnalogTypeMap.empty ())
1773  {
1774  AJAAncillaryAnalogTypeMap::const_iterator it (gAnalogTypeMap.find (inLineNum));
1775  if (it != gAnalogTypeMap.end ())
1776  ancType = it->second;
1777  }
1778  return ancType;
1779 }
gGlobalLock
static AJALock gGlobalLock
Definition: ancillarylist.cpp:120
AJAAncillaryList::AllowMultiRTPReceive
virtual bool AllowMultiRTPReceive(void) const
Answers true if multiple RTP packets are allowed for capture/receive. The default behavior is to proc...
Definition: ancillarylist.h:547
AJAAncPktCounts
UByteSequence AJAAncPktCounts
Ordered sequence of SMPTE Anc packet counts.
Definition: ancillarylist.h:42
AJAAncBufferFormat_FBVANC
@ AJAAncBufferFormat_FBVANC
Frame buffer VANC lines.
Definition: ancillarydata.h:499
AJA_STATUS_BADBUFFERSIZE
@ AJA_STATUS_BADBUFFERSIZE
Definition: types.h:411
ULWordSequenceToStringBE
static string ULWordSequenceToStringBE(const ULWordSequence &inData, const size_t inMaxNum=32)
Definition: ancillarylist.cpp:84
SortByDID
static bool SortByDID(AJAAncillaryData *lhs, AJAAncillaryData *rhs)
Definition: ancillarylist.cpp:414
AJAAncillaryList::AJAAncillaryDataList
std::vector< AJAAncillaryData * > AJAAncillaryDataList
Definition: ancillarylist.h:612
ULWordSequenceConstIter
ULWordSequence::const_iterator ULWordSequenceConstIter
A handy const iterator for iterating over a ULWordSequence.
Definition: ntv2publicinterface.h:47
AJAAncillaryList::ClearAnalogAncillaryDataTypeMap
static AJAStatus ClearAnalogAncillaryDataTypeMap(void)
Clears my global Analog Ancillary Data Type map.
Definition: ancillarylist.cpp:1730
AJAAncillaryData::GetRawPacketSize
virtual AJAStatus GetRawPacketSize(uint32_t &outPacketSize) const
Returns the number of "raw" ancillary data bytes that will be generated by AJAAncillaryData::Generate...
Definition: ancillarydata.cpp:726
AJAAncDataLoc
Defines where the ancillary data can be found within a video stream.
Definition: ancillarydata.h:225
AppendUWordPacketToGump
static AJAStatus AppendUWordPacketToGump(UByteSequence &outGumpPkt, const UWordSequence &inPacketWords, const AJAAncDataLoc inLoc=AJAAncDataLoc(AJAAncDataLink_A, AJAAncDataChannel_Y, AJAAncDataSpace_VANC, 0))
Definition: ancillarylist.cpp:791
AJARTPAncPayloadHeader::SetAncPacketCount
virtual AJARTPAncPayloadHeader & SetAncPacketCount(const uint8_t inPktCount)
Sets my RTP Anc Packet Count value.
Definition: ancillarydata.h:1337
AJAAncillaryList::AddVANCData
virtual AJAStatus AddVANCData(const UWordSequence &inPacketWords, const AJAAncillaryDataLocation &inLocation, const uint32_t inFrameNum=0)
Adds the packet that originated in the VANC lines of an NTV2 frame buffer to my list.
Definition: ancillarylist.cpp:840
NTV2Buffer::GetU32s
bool GetU32s(ULWordSequence &outU32s, const size_t inU32Offset=0, const size_t inMaxSize=32, const bool inByteSwap=false) const
Answers with my contents as a vector of unsigned 32-bit values.
Definition: ntv2publicinterface.cpp:536
AJAAncillaryList::Compare
virtual AJAStatus Compare(const AJAAncillaryList &inCompareList, const bool inIgnoreLocation=true, const bool inIgnoreChecksum=true) const
Compares me with another list.
Definition: ancillarylist.cpp:467
AJAAncillaryList::GetAncillaryDataTransmitData
virtual AJAStatus GetAncillaryDataTransmitData(const bool inIsProgressive, const uint32_t inF2StartLine, uint8_t *pOutF1AncData, const uint32_t inF1ByteCountMax, uint8_t *pOutF2AncData, const uint32_t inF2ByteCountMax)
Builds one or two ancillary data buffers (one for field 1, one for field 2) with the anc data inserte...
Definition: ancillarylist.cpp:1266
AJAAncDataType_Unknown
@ AJAAncDataType_Unknown
Includes data that is valid, but we don't recognize.
Definition: ancillarydata.h:46
NTV2FormatDescriptor
Describes a video frame for a given video standard or format and pixel format, including the total nu...
Definition: ntv2formatdescriptor.h:41
NTV2FormatDescriptor::GetRowAddress
const void * GetRowAddress(const void *pInStartAddress, const ULWord inRowIndex0, const UWord inPlaneIndex0=0) const
Definition: ntv2formatdescriptor.cpp:997
AJAAncillaryList::SetAnalogAncillaryDataTypeMap
static AJAStatus SetAnalogAncillaryDataTypeMap(const AJAAncillaryAnalogTypeMap &inMap)
Copies the given map to the global Analog Ancillary Data Type map.
Definition: ancillarylist.cpp:1738
AJAAncillaryList::RemoveAncillaryData
virtual AJAStatus RemoveAncillaryData(AJAAncillaryData *pInAncData)
Removes all copies of the AJAAncillaryData object from me.
Definition: ancillarylist.cpp:378
AJAAncillaryList::SetFromDeviceAncBuffers
static AJAStatus SetFromDeviceAncBuffers(const NTV2Buffer &inF1AncBuffer, const NTV2Buffer &inF2AncBuffer, AJAAncillaryList &outPackets, const uint32_t inFrameNum=0)
Returns all ancillary data packets found in the given F1 and F2 ancillary data buffers.
Definition: ancillarylist.cpp:1076
NTV2Buffer
A generic user-space buffer object that has an address and a length. Used most often to share an arbi...
Definition: ntv2publicinterface.h:5993
AJA_STATUS_SUCCESS
@ AJA_STATUS_SUCCESS
Definition: types.h:381
ToAJAAncPktDIDSID
#define ToAJAAncPktDIDSID(_d_, _s_)
Definition: ancillarydata.h:29
AJA_STATUS_NOT_FOUND
@ AJA_STATUS_NOT_FOUND
Definition: types.h:402
NTV2Buffer::GetByteCount
ULWord GetByteCount(void) const
Definition: ntv2publicinterface.h:6066
XMTDBG
#define XMTDBG(__x__)
Definition: ancillarylist.cpp:43
NTV2_ASSERT
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:506
AJAAncillaryList::SetFromDeviceAuxBuffers
static AJAStatus SetFromDeviceAuxBuffers(const NTV2Buffer &inF1AuxBuffer, const NTV2Buffer &inF2AuxBuffer, AJAAncillaryList &outPackets, const uint32_t inFrameNum=0)
Returns all HDMI Aux data packets found in the given F1 and F2 aux data buffers.
Definition: ancillarylist.cpp:1093
NTV2Buffer::IsProvidedByClient
bool IsProvidedByClient(void) const
Definition: ntv2publicinterface.h:6078
AJAAncillaryList::GetIPTransmitData
virtual AJAStatus GetIPTransmitData(NTV2Buffer &F1Buffer, NTV2Buffer &F2Buffer, const bool inIsProgressive=true, const uint32_t inF2StartLine=0)
Explicitly encodes my AJAAncillaryData packets into the given buffers in RTP Anc Buffer Data Format ....
Definition: ancillarylist.cpp:1581
UByteSequence
std::vector< uint8_t > UByteSequence
An ordered sequence of UByte (uint8_t) values.
Definition: ntv2publicinterface.h:38
AJAAncPktDIDSIDSet
std::set< AJAAncPktDIDSID > AJAAncPktDIDSIDSet
Set of distinct packet DID/SIDs (New in SDK 16.0)
Definition: ancillarylist.h:44
AncChannelSearch_C
@ AncChannelSearch_C
Only look in chroma samples.
Definition: ancillarydata.h:155
ancillarylist.h
Declares the AJAAncillaryList class.
YUVComponentsTo10BitYUVPackedBuffer
bool YUVComponentsTo10BitYUVPackedBuffer(const std::vector< uint16_t > &inYCbCrLine, NTV2Buffer &inFrameBuffer, const NTV2FormatDescriptor &inDescriptor, const UWord inLineOffset)
Packs up to one raster line of uint16_t YUV components into an NTV2_FBF_10BIT_YCBCR frame buffer.
AJAAncillaryData::GetAncPacketsFromVANCLine
static bool GetAncPacketsFromVANCLine(const UWordSequence &inYUV16Line, const AncChannelSearchSelect inChanSelect, U16Packets &outRawPackets, U16Packet &outWordOffsets)
Extracts whatever VANC packets are found inside the given 16-bit YUV line buffer.
Definition: ancillarydata.cpp:1710
AJAU32PktsConstIter
AJAU32Pkts::const_iterator AJAU32PktsConstIter
Handy const iterator over AJAU32Pkts.
Definition: ancillarylist.h:39
NTV2FormatDescriptor::GetVisibleRasterBytes
ULWord GetVisibleRasterBytes(const UWord inPlaneIndex0=0) const
Definition: ntv2formatdescriptor.h:134
AJAAncDataType
AJAAncDataType
Identifies the ancillary data types that are known to this module.
Definition: ancillarydata.h:44
AJAAncillaryList::CountAncillaryDataWithType
virtual uint32_t CountAncillaryDataWithType(const AJAAncDataType inMatchType) const
Answers with the number of AJAAncillaryData objects having the given type.
Definition: ancillarylist.cpp:222
UnpackLine_10BitYUVtoUWordSequence
bool UnpackLine_10BitYUVtoUWordSequence(const void *pIn10BitYUVLine, const NTV2FormatDescriptor &inFormatDesc, UWordSequence &out16BitYUVLine)
Unpacks a line of NTV2_FBF_10BIT_YCBCR video into 16-bit-per-component YUV data.
Definition: ntv2utils.cpp:143
AJAAncillaryData::InitAuxWithReceivedData
virtual AJAStatus InitAuxWithReceivedData(const uint8_t *pInData, const size_t inMaxBytes, uint32_t &outPacketByteCount)
Initializes me from "raw" ancillary data received from hardware (ingest) – see SDI Anc Buffer Data Fo...
Definition: ancillarydata.cpp:624
AJAAncillaryData::InitWithReceivedData
virtual AJAStatus InitWithReceivedData(const uint8_t *pInData, const size_t inMaxBytes, const AJAAncDataLoc &inLocationInfo, uint32_t &outPacketByteCount)
Initializes me from "raw" ancillary data received from hardware (ingest) – see SDI Anc Buffer Data Fo...
Definition: ancillarydata.cpp:512
AJAAncillaryList::ParseAllAncillaryData
virtual AJAStatus ParseAllAncillaryData(void)
Sends a "ParsePayloadData" command to all of my AJAAncillaryData objects.
Definition: ancillarylist.cpp:205
DEC0N
#define DEC0N(__x__, __n__)
Definition: ntv2publicinterface.h:5607
AJAAncillaryList::GetAncillaryDataWithID
virtual AJAAncillaryData * GetAncillaryDataWithID(const uint8_t inDID, const uint8_t inSID, const uint32_t inIndex=0) const
Answers with the AJAAncillaryData object having the given DataID and SecondaryID, at the given index.
Definition: ancillarylist.cpp:281
RCVDBG
#define RCVDBG(__x__)
Definition: ancillarylist.cpp:37
NTV2FrameBufferFormat
NTV2FrameBufferFormat
Identifies a particular video frame buffer format. See Device Frame Buffer Formats for details.
Definition: ntv2enums.h:207
ancillarydatafactory.h
Declaration of the AJAAncillaryDataFactory class.
NTV2Buffer::PutU32s
bool PutU32s(const ULWordSequence &inU32s, const size_t inU32Offset=0, const bool inByteSwap=false)
Copies a vector of unsigned 32-bit values into me.
Definition: ntv2publicinterface.cpp:730
NTV2FormatDescriptor::GetLineOffsetFromSMPTELine
bool GetLineOffsetFromSMPTELine(const ULWord inSMPTELine, ULWord &outLineOffset) const
Answers with the equivalent line offset into the raster I describe for the given SMPTE line number.
Definition: ntv2formatdescriptor.cpp:1200
AJAAncillaryList::GetAncillaryPacketIDs
virtual AJAAncPktDIDSIDSet GetAncillaryPacketIDs(void) const
Definition: ancillarylist.cpp:304
AJAAncillaryList::GetAncillaryDataWithType
virtual AJAAncillaryData * GetAncillaryDataWithType(const AJAAncDataType inMatchType, const uint32_t inIndex=0) const
Answers with the AJAAncillaryData object having the given type and index.
Definition: ancillarylist.cpp:238
ENDIAN_32NtoH
static uint32_t ENDIAN_32NtoH(const uint32_t inValue)
Definition: ancillarylist.cpp:63
AJA_ENDIAN_32NtoH
#define AJA_ENDIAN_32NtoH(__val__)
Definition: ancillarylist.cpp:57
AJAAncillaryList
I am an ordered collection of AJAAncillaryData instances which represent one or more SMPTE 291 data p...
Definition: ancillarylist.h:64
AJAAncillaryList::SortListBySID
virtual AJAStatus SortListBySID(void)
Sort the AncillaryDataList by Secondary ID (SID) value.
Definition: ancillarylist.cpp:446
AJAAncBufferFormat_HDMI
@ AJAAncBufferFormat_HDMI
HDMI.
Definition: ancillarydata.h:502
LOGMYDEBUG
#define LOGMYDEBUG(__x__)
Definition: ancillarylist.cpp:31
AJARTPAncPayloadHeader::SetEndOfFieldOrFrame
virtual AJARTPAncPayloadHeader & SetEndOfFieldOrFrame(const bool inIsLast=true)
Sets my RTP Packet End-Of-Field or End-Of-Frame (Marker Bit) value.
Definition: ancillarydata.h:1372
AJAAncillaryData::Unpack8BitYCbCrToU16sVANCLine
static bool Unpack8BitYCbCrToU16sVANCLine(const void *pInYUV8Line, U16Packet &outU16YUVLine, const uint32_t inNumPixels)
Converts a single line of NTV2_FBF_8BIT_YCBCR data from the given source buffer into an ordered seque...
Definition: ancillarydata.cpp:1782
AJAAncillaryList::SetIncludeZeroLengthPackets
static void SetIncludeZeroLengthPackets(const bool inExclude)
Sets whether or not zero-length packets are included or not.
Definition: ancillarylist.cpp:137
AJAAncillaryDataFactory::Create
static AJAAncillaryData * Create(const AJAAncDataType inAncType, const AJAAncillaryData &inAncData)
Creates a new particular subtype of AJAAncillaryData object.
Definition: ancillarydatafactory.cpp:23
AJAAncDataLoc::IsLumaChannel
bool IsLumaChannel(void) const
Definition: ancillarydata.h:307
AJAAncillaryList::GetAnalogAncillaryDataTypeMap
static AJAStatus GetAnalogAncillaryDataTypeMap(AJAAncillaryAnalogTypeMap &outMap)
Returns a copy of the global Analog Ancillary Data Type map.
Definition: ancillarylist.cpp:1746
AJAStatus
AJAStatus
Definition: types.h:378
AJAAncillaryList::AJAAncDataListConstIter
AJAAncillaryDataList::const_iterator AJAAncDataListConstIter
Handy const iterator for iterating over members of an AJAAncillaryDataList.
Definition: ancillarylist.h:616
AJAAncillaryAnalogTypeMap
std::map< uint16_t, AJAAncDataType > AJAAncillaryAnalogTypeMap
Associates certain frame line numbers with specific types of "raw" or "analog" ancillary data....
Definition: ancillarylist.h:36
AJARTPAncPayloadHeader
I represent the header of a SMPTE 2110 compliant RTP Anc network packet.
Definition: ancillarydata.h:1185
AJAAncillaryList::AJAAncDataListIter
AJAAncillaryDataList::iterator AJAAncDataListIter
Handy non-const iterator for iterating over members of an AJAAncillaryDataList.
Definition: ancillarylist.h:617
AJARTPAncPayloadHeader::WriteToULWordVector
virtual bool WriteToULWordVector(ULWordSequence &outVector, const bool inReset=true) const
Writes an RTP packet header based on my current state into the given ULWordSequence....
Definition: ancillarydata.cpp:2280
lock.h
Declares the AJALock class.
AJA_STATUS_FAIL
@ AJA_STATUS_FAIL
Definition: types.h:382
NTV2Buffer::IsNULL
bool IsNULL(void) const
Definition: ntv2publicinterface.h:6088
ULWord
uint32_t ULWord
Definition: ajatypes.h:253
AJAAncillaryData::Compare
virtual AJAStatus Compare(const AJAAncillaryData &inRHS, const bool inIgnoreLocation=true, const bool inIgnoreChecksum=true) const
Compares me with another packet.
Definition: ancillarydata.cpp:1510
gAnalogTypeMapMutex
static AJALock gAnalogTypeMapMutex
Definition: ancillarylist.cpp:1727
AJAAncillaryData
I am the principal class that stores a single SMPTE-291 SDI ancillary data packet OR the digitized co...
Definition: ancillarydata.h:552
AJAAncillaryList::SortListByDID
virtual AJAStatus SortListByDID(void)
Sort the AncillaryDataList by DataID (DID) value.
Definition: ancillarylist.cpp:435
AJAAncDataChannel_Y
@ AJAAncDataChannel_Y
The ancillary data is associated with the luminance (Y) channel of the video stream.
Definition: ancillarydata.h:133
AJARTPAncPayloadHeader::SetPayloadLength
virtual AJARTPAncPayloadHeader & SetPayloadLength(const uint16_t inByteCount)
Sets my RTP Packet Length value.
Definition: ancillarydata.h:1330
AJAAncillaryList::GetExcludedZeroLengthPacketCount
static uint32_t GetExcludedZeroLengthPacketCount(void)
Definition: ancillarylist.cpp:122
AJAAncillaryData::GetPayloadData
virtual const uint8_t * GetPayloadData(void) const
Definition: ancillarydata.h:801
UWordSequenceConstIter
UWordSequence::const_iterator UWordSequenceConstIter
A handy const iterator for iterating over a UWordSequence.
Definition: ntv2publicinterface.h:43
UWordSequence
std::vector< uint16_t > UWordSequence
An ordered sequence of UWord (uint16_t) values.
Definition: ntv2publicinterface.h:42
MAX_RTP_PKT_LENGTH_BYTES
static const size_t MAX_RTP_PKT_LENGTH_BYTES(0x0000FFFF)
AJARTPAncPayloadHeader::ReadFromBuffer
virtual bool ReadFromBuffer(const NTV2Buffer &inBuffer)
Resets my current state from the RTP packet header stored in the given buffer. Each 32-bit word in th...
Definition: ancillarydata.cpp:2313
AJARTPAncPayloadHeader::SetField2
virtual AJARTPAncPayloadHeader & SetField2(void)
Sets my Field Signal value to "Field 2".
Definition: ancillarydata.h:1310
AJAAncillaryList::SetAnalogAncillaryDataTypeForLine
static AJAStatus SetAnalogAncillaryDataTypeForLine(const uint16_t inLineNum, const AJAAncDataType inType)
Sets (or changes) the map entry for the designated line to the designated type.
Definition: ancillarylist.cpp:1754
UnpackLine_10BitYUVtoU16s
bool UnpackLine_10BitYUVtoU16s(std::vector< uint16_t > &outYCbCrLine, const NTV2Buffer &inFrameBuffer, const NTV2FormatDescriptor &inDescriptor, const UWord inLineOffset)
Unpacks up to one raster line of an NTV2_FBF_10BIT_YCBCR frame buffer into an array of uint16_t value...
AJAAncillaryList::DeleteAncillaryData
virtual AJAStatus DeleteAncillaryData(AJAAncillaryData *pInAncData)
Removes all copies of the AJAAncillaryData object from me and deletes the object itself.
Definition: ancillarylist.cpp:400
LOGMYINFO
#define LOGMYINFO(__x__)
Definition: ancillarylist.cpp:30
SortBySID
static bool SortBySID(AJAAncillaryData *lhs, AJAAncillaryData *rhs)
Definition: ancillarylist.cpp:420
NTV2FormatDescriptor::GetFirstActiveLine
ULWord GetFirstActiveLine(void) const
Definition: ntv2formatdescriptor.h:180
AJAAncillaryDataWildcard_DID
const uint8_t AJAAncillaryDataWildcard_DID
Definition: ancillarylist.h:27
UWord
uint16_t UWord
Definition: ajatypes.h:251
AJAAncillaryList::IsIncludingZeroLengthPackets
static bool IsIncludingZeroLengthPackets(void)
Definition: ancillarylist.cpp:132
AJAAncillaryData::AppendPayload
virtual AJAStatus AppendPayload(const AJAAncillaryData &inAncData)
Appends payload data from another AJAAncillaryData object to my existing payload.
Definition: ancillarydata.cpp:426
NTV2_FBF_8BIT_YCBCR
@ NTV2_FBF_8BIT_YCBCR
See 8-Bit YCbCr Format.
Definition: ntv2enums.h:211
ntv2utils.h
Declares numerous NTV2 utility functions.
AJAU32Pkts
std::vector< ULWordSequence > AJAU32Pkts
Ordered sequence of U32 RTP packets (U32s in network byte order)
Definition: ancillarylist.h:38
AJA_SUCCESS
#define AJA_SUCCESS(_status_)
Definition: types.h:370
AJAAncDataType_HDMI_Aux
@ AJAAncDataType_HDMI_Aux
HDMI Auxiliary data.
Definition: ancillarydata.h:60
AJAAncillaryList::GetAncillaryDataAtIndex
virtual AJAAncillaryData * GetAncillaryDataAtIndex(const uint32_t inIndex) const
Answers with the AJAAncillaryData object at the given index.
Definition: ancillarylist.cpp:189
AJAAncillaryData::AsString
virtual std::string AsString(const uint16_t inDumpMaxBytes=0) const
Definition: ancillarydata.cpp:1440
AJAAncillaryData::SetBufferFormat
virtual AJAAncillaryData & SetBufferFormat(const AJAAncBufferFormat inFmt)
Sets my originating buffer format.
Definition: ancillarydata.h:781
BumpZeroLengthPacketCount
static void BumpZeroLengthPacketCount(void)
Definition: ancillarylist.cpp:142
AJAAncBufferFormat_SDI
@ AJAAncBufferFormat_SDI
SDI (AJA "GUMP")
Definition: ancillarydata.h:500
AJAAncillaryList::AddAncillaryData
virtual AJAStatus AddAncillaryData(const AJAAncillaryList &inPackets)
Appends a copy of the given list's packets to me.
Definition: ancillarylist.cpp:317
LOGMYERROR
#define LOGMYERROR(__x__)
Definition: ancillarylist.cpp:27
AJAAncDataLoc
struct AJAAncDataLoc AJAAncDataLoc
Defines where the ancillary data can be found within a video stream.
AJAAncillaryList::StripNativeInserterGUMPPackets
static bool StripNativeInserterGUMPPackets(const NTV2Buffer &inSrc, NTV2Buffer &outDst)
Copies GUMP from inSrc to outDst buffers, but removes ATC, VPID, VITC, EDH & raw/analog packets.
Definition: ancillarylist.cpp:1654
AJAAncillaryList::Print
virtual std::ostream & Print(std::ostream &inOutStream, const bool inDetailed=true) const
Dumps a human-readable description of every packet in my list to the given output stream.
Definition: ancillarylist.cpp:1639
AJAAncillaryList::AllowMultiRTPTransmit
virtual bool AllowMultiRTPTransmit(void) const
Answers true if multiple RTP packets will be transmitted/encoded. The default behavior is to transmit...
Definition: ancillarylist.h:474
AJAAncillaryList::CountAncillaryData
virtual uint32_t CountAncillaryData(void) const
Answers with the number of AJAAncillaryData objects I contain (any/all types).
Definition: ancillarylist.h:199
AJAAncillaryList::WriteRTPPackets
static AJAStatus WriteRTPPackets(NTV2Buffer &theBuffer, uint32_t &outBytesWritten, const AJAU32Pkts &inRTPPkts, const AJAAncPktCounts &inAncCounts, const bool inIsF2, const bool inIsProgressive)
Fills the buffer with the given RTP packets.
Definition: ancillarylist.cpp:1505
AJARTPAncPayloadHeader::SetSequenceNumber
virtual AJARTPAncPayloadHeader & SetSequenceNumber(const uint32_t inSeqNumber)
Sets my RTP Packet Sequence Number value.
Definition: ancillarydata.h:1358
IS_VALID_AJAAncDataChannel
#define IS_VALID_AJAAncDataChannel(_x_)
Definition: ancillarydata.h:138
AJAAncillaryList::GetAnalogAncillaryDataTypeForLine
static AJAAncDataType GetAnalogAncillaryDataTypeForLine(const uint16_t inLineNum)
Answers with the ancillary data type associated with the designated line.
Definition: ancillarylist.cpp:1768
AJAAncillaryList::GetAncillaryDataTransmitSize
virtual AJAStatus GetAncillaryDataTransmitSize(const bool inIsProgressive, const uint32_t inF2StartLine, uint32_t &outF1ByteCount, uint32_t &outF2ByteCount)
Answers with the sizes of the buffers (one for field 1, one for field 2) needed to hold the anc data ...
Definition: ancillarylist.cpp:1240
AJA_STATUS_UNSUPPORTED
@ AJA_STATUS_UNSUPPORTED
Definition: types.h:394
AJALock
Definition: lock.h:30
AJAAncillaryData::Unpack8BitYCbCrToU16sVANCLineSD
static bool Unpack8BitYCbCrToU16sVANCLineSD(const void *pInYUV8Line, UWordSequence &outU16YUVLine, const uint32_t inNumPixels)
SD version of Unpack8BitYCbCrToU16sVANCLine.
Definition: ancillarydata.cpp:1884
AJA_STATUS_RANGE
@ AJA_STATUS_RANGE
Definition: types.h:385
AJARTPAncPayloadHeader::SetProgressive
virtual AJARTPAncPayloadHeader & SetProgressive(void)
Sets my Field Signal value to "Progressive".
Definition: ancillarydata.h:1316
AJAAncillaryList::~AJAAncillaryList
virtual ~AJAAncillaryList()
My destructor.
Definition: ancillarylist.cpp:167
NTV2FormatDescriptor::GetTotalRasterBytes
ULWord GetTotalRasterBytes(const UWord inPlaneIndex0=0) const
Definition: ntv2formatdescriptor.h:114
AJA_NULL
#define AJA_NULL
Definition: ajatypes.h:197
AJAAncillaryList::CompareWithInfo
virtual std::string CompareWithInfo(const AJAAncillaryList &inCompareList, const bool inIgnoreLocation=true, const bool inIgnoreChecksum=true) const
Compares me with another list and returns a std::string that contains a human-readable explanation of...
Definition: ancillarylist.cpp:482
AJAAncDataLoc::SetHorizontalOffset
AJAAncDataLoc & SetHorizontalOffset(uint16_t inHOffset)
Specifies the horizontal packet position in the raster.
Definition: ancillarydata.h:408
AJAAncDataLink
AJAAncDataLink
Identifies which link of a video stream the ancillary data is associated with.
Definition: ancillarydata.h:79
AJARTPAncPayloadHeader::IsNULL
virtual bool IsNULL(void) const
Definition: ancillarydata.cpp:2361
NTV2Buffer::GetHostAddress
void * GetHostAddress(const ULWord inByteOffset, const bool inFromEnd=false) const
Definition: ntv2publicinterface.cpp:1686
AJAAncillaryList::GetVANCTransmitData
virtual AJAStatus GetVANCTransmitData(NTV2Buffer &inFrameBuffer, const NTV2FormatDescriptor &inFormatDesc)
Writes my AJAAncillaryData objects into the given tall/taller frame buffer having the given raster/fo...
Definition: ancillarylist.cpp:1325
NTV2Buffer::GetHostPointer
void * GetHostPointer(void) const
Definition: ntv2publicinterface.h:6049
AJAAutoLock
Definition: lock.h:91
AJARTPAncPayloadHeader::ReadFromULWordVector
virtual bool ReadFromULWordVector(const ULWordSequence &inVector)
Resets my current state from the RTP packet header stored in the given ULWordSequence....
Definition: ancillarydata.cpp:2302
NTV2Buffer::AsString
std::string AsString(UWord inDumpMaxBytes=0) const
Definition: ntv2publicinterface.cpp:326
LOGMYWARN
#define LOGMYWARN(__x__)
Definition: ancillarylist.cpp:28
AJAAncillaryList::CountAncillaryDataWithID
virtual uint32_t CountAncillaryDataWithID(const uint8_t inDID, const uint8_t inSID) const
Answers with the number of AncillaryData objects having the given DataID and SecondaryID.
Definition: ancillarylist.cpp:263
AJAAncillaryData::SetFrameID
virtual AJAAncillaryData & SetFrameID(const uint32_t inFrameID)
Sets my originating frame identifier.
Definition: ancillarydata.h:774
NTV2_FBF_10BIT_YCBCR
@ NTV2_FBF_10BIT_YCBCR
See 10-Bit YCbCr Format.
Definition: ntv2enums.h:210
AJAAtomic::Increment
static int32_t Increment(int32_t volatile *pTarget)
Definition: atomic.cpp:82
gIncludeZeroLengthPackets
static bool gIncludeZeroLengthPackets(false)
RCVWARN
#define RCVWARN(__x__)
Definition: ancillarylist.cpp:34
operator<<
ostream & operator<<(ostream &inOutStream, const AJAU32Pkts &inPkts)
Definition: ancillarylist.cpp:91
AJA_STATUS_NULL
@ AJA_STATUS_NULL
Definition: types.h:387
DEC
#define DEC(__x__)
Definition: ntv2publicinterface.h:5605
AJAAncillaryList::BufferHasGUMPData
static bool BufferHasGUMPData(const NTV2Buffer &inBuffer)
Definition: ancillarylist.h:621
MAX_RTP_PKT_LENGTH_WORDS
static const size_t MAX_RTP_PKT_LENGTH_WORDS((MAX_RTP_PKT_LENGTH_BYTES+1)/sizeof(uint32_t) - 1)
false
#define false
Definition: ntv2devicefeatures.h:25
AJAAncillaryData::Clear
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values.
Definition: ancillarydata.cpp:159
PrintULWordsBE
static ostream & PrintULWordsBE(ostream &inOutStream, const ULWordSequence &inData, const size_t inMaxNum=32)
Definition: ancillarylist.cpp:66
gAnalogTypeMap
static AJAAncillaryAnalogTypeMap gAnalogTypeMap
Definition: ancillarylist.cpp:1726
NTV2FormatDescriptor::GetWriteableRowAddress
void * GetWriteableRowAddress(void *pInStartAddress, const ULWord inRowIndex0, const UWord inPlaneIndex0=0) const
Definition: ntv2formatdescriptor.cpp:1018
AJAAncDataChannel_C
@ AJAAncDataChannel_C
The ancillary data is associated with the chrominance (C) channel of the video stream.
Definition: ancillarydata.h:131
NTV2_IS_SD_STANDARD
#define NTV2_IS_SD_STANDARD(__s__)
Definition: ntv2enums.h:186
AJAAncillaryList::AddReceivedAncillaryData
virtual AJAStatus AddReceivedAncillaryData(const NTV2Buffer &inReceivedData, const uint32_t inFrameNum=0)
Parse "raw" ancillary data bytes received from hardware (ingest) – see SDI Anc Buffer Data Format – i...
Definition: ancillarylist.cpp:542
HEX0N
#define HEX0N(__x__, __n__)
Definition: debug.cpp:1175
NTV2FrameBufferFormatToString
std::string NTV2FrameBufferFormatToString(const NTV2FrameBufferFormat inValue, const bool inForRetailDisplay=false)
Definition: ntv2utils.cpp:6940
AJAAncillaryData::ParsePayloadData
virtual AJAStatus ParsePayloadData(void)
Parses (interprets) the "local" ancillary data from my payload data.
Definition: ancillarydata.cpp:501
AJA_STATUS_BAD_PARAM
@ AJA_STATUS_BAD_PARAM
Definition: types.h:392
AJAAncillaryList::ResetExcludedZeroLengthPacketCount
static void ResetExcludedZeroLengthPacketCount(void)
Resets my tally of excluded zero-length packets to zero.
Definition: ancillarylist.cpp:127
AJAAncillaryList::GetTransmitData
virtual AJAStatus GetTransmitData(NTV2Buffer &F1Buffer, NTV2Buffer &F2Buffer, const bool inIsProgressive=true, const uint32_t inF2StartLine=0)
Encodes my AJAAncillaryData packets into the given buffers in the default SDI Anc Buffer Data Format ...
Definition: ancillarylist.cpp:1277
std
Definition: json.hpp:5362
AJAAncillaryDataWildcard_SID
const uint8_t AJAAncillaryDataWildcard_SID
Definition: ancillarylist.h:28
AJAStatusToString
std::string AJAStatusToString(const AJAStatus inStatus, const bool inDetailed)
Definition: debug.cpp:981
AJAAncillaryList::SortListByLocation
virtual AJAStatus SortListByLocation(void)
Sort the AncillaryDataList by "location", i.e. where in the video (field, line num,...
Definition: ancillarylist.cpp:456
ULWordSequence
std::vector< uint32_t > ULWordSequence
An ordered sequence of ULWord (uint32_t) values.
Definition: ntv2publicinterface.h:46
AJAAncillaryDataFactory::GuessAncillaryDataType
static AJAAncDataType GuessAncillaryDataType(const AJAAncillaryData &inAncData)
Given a generic AJAAncillaryData object, attempts to guess what kind of specific AJAAncillaryData obj...
Definition: ancillarydatafactory.cpp:65
atomic.h
Declares the AJAAtomic class.
AJAAncillaryData::GenerateTransmitData
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 F...
Definition: ancillarydata.cpp:767
SortByLocation
static bool SortByLocation(AJAAncillaryData *lhs, AJAAncillaryData *rhs)
Definition: ancillarylist.cpp:425
AJAAncillaryList::operator=
virtual AJAAncillaryList & operator=(const AJAAncillaryList &inRHS)
Assignment operator – replaces my contents with the right-hand-side value.
Definition: ancillarylist.cpp:173
AJAAncillaryData::Clone
virtual AJAAncillaryData * Clone(void) const
Definition: ancillarydata.cpp:165
true
#define true
Definition: ntv2devicefeatures.h:26
AJAAncDataCoding_Digital
@ AJAAncDataCoding_Digital
The ancillary data is in the form of a SMPTE-291 Ancillary Packet.
Definition: ancillarydata.h:476
gExcludedZeroLengthPackets
static uint32_t gExcludedZeroLengthPackets(0)
AJAAncillaryList::GetAnalogAncillaryDataType
virtual AJAAncDataType GetAnalogAncillaryDataType(const AJAAncillaryData &inAncData)
Definition: ancillarylist.h:619
AJARTPAncPayloadHeader::SetField1
virtual AJARTPAncPayloadHeader & SetField1(void)
Sets my Field Signal value to "Field 1".
Definition: ancillarydata.h:1304
AJAAncillaryData::CompareWithInfo
virtual std::string CompareWithInfo(const AJAAncillaryData &inRHS, const bool inIgnoreLocation=true, const bool inIgnoreChecksum=true) const
Compares me with another packet and returns a string that describes what's different.
Definition: ancillarydata.cpp:1537
AJARTPAncPayloadHeader::BufferStartsWithRTPHeader
static bool BufferStartsWithRTPHeader(const NTV2Buffer &inBuffer)
Definition: ancillarydata.cpp:2172
RCVFAIL
#define RCVFAIL(__x__)
Definition: ancillarylist.cpp:33
AJAAncillaryList::AJAAncillaryList
AJAAncillaryList()
Instantiate and initialize with a default set of values.
Definition: ancillarylist.cpp:151
AJAAncillaryList::AddFromDeviceAuxBuffer
static AJAStatus AddFromDeviceAuxBuffer(const NTV2Buffer &inAuxBuffer, AJAAncillaryList &outPacketList, const uint32_t inFrameNum=0)
Appends whatever can be decoded from the given device HDIM aux buffer to the AJAAncillaryList.
Definition: ancillarylist.cpp:1052
AJAAncBufferFormat_RTP
@ AJAAncBufferFormat_RTP
RTP/IP.
Definition: ancillarydata.h:501
NTV2Buffer::Fill
bool Fill(const T &inValue)
Fills me with the given scalar value.
Definition: ntv2publicinterface.h:6218
AJARTPAncPayloadHeader::IsValid
virtual bool IsValid(void) const
Definition: ancillarydata.cpp:2366
AJAAncDataSpace_VANC
@ AJAAncDataSpace_VANC
Ancillary data found between SAV and EAV (.
Definition: ancillarydata.h:177
AJAAncillaryList::Clear
virtual AJAStatus Clear(void)
Removes and frees all of my AJAAncillaryData objects.
Definition: ancillarylist.cpp:357
AJAAncillaryList::GetIPTransmitDataLength
virtual AJAStatus GetIPTransmitDataLength(uint32_t &outF1ByteCount, uint32_t &outF2ByteCount, const bool inIsProgressive=true, const uint32_t inF2StartLine=0)
Answers with the number of bytes required to store IP/RTP for my AJAAncillaryData packets in RTP Anc ...
Definition: ancillarylist.cpp:1618
AJA_STATUS_BADBUFFERCOUNT
@ AJA_STATUS_BADBUFFERCOUNT
Definition: types.h:410
AJAAncillaryList::IgnoreChecksumErrors
virtual bool IgnoreChecksumErrors(void) const
Answers if checksum errors are to be ignored or not. The default behavior is to not ignore them.
Definition: ancillarylist.h:562
xHEX0N
#define xHEX0N(__x__, __n__)
Definition: ntv2publicinterface.h:5604
AJA_FAILURE
#define AJA_FAILURE(_status_)
Definition: types.h:371
AJAAncDataType_Cea608_Line21
@ AJAAncDataType_Cea608_Line21
CEA608 SD Closed Captioning ("Line 21" waveform)
Definition: ancillarydata.h:52
AJAAncillaryList::AddFromDeviceAncBuffer
static AJAStatus AddFromDeviceAncBuffer(const NTV2Buffer &inAncBuffer, AJAAncillaryList &outPacketList, const uint32_t inFrameNum=0)
Appends whatever can be decoded from the given device Anc buffer to the AJAAncillaryList.
Definition: ancillarylist.cpp:971
IS_VALID_AJAAncDataType
#define IS_VALID_AJAAncDataType(_x_)
Definition: ancillarydata.h:64
AJAAncillaryList::GetRTPPackets
virtual AJAStatus GetRTPPackets(AJAU32Pkts &outF1U32Pkts, AJAU32Pkts &outF2U32Pkts, AJAAncPktCounts &outF1AncCounts, AJAAncPktCounts &outF2AncCounts, const bool inIsProgressive, const uint32_t inF2StartLine)
Answers with my F1 & F2 SMPTE anc packets encoded as RTP ULWordSequences. The returned ULWords are al...
Definition: ancillarylist.cpp:1116
NTV2FormatDescriptor::IsValid
bool IsValid(void) const
Definition: ntv2formatdescriptor.h:94
AJAAncPktDIDSIDSetConstIter
AJAAncPktDIDSIDSet::const_iterator AJAAncPktDIDSIDSetConstIter
Handy const iterator for AJAAncPktDIDSIDSet (New in SDK 16.0)
Definition: ancillarylist.h:47
NTV2FormatDescriptor::GetSMPTELineNumber
bool GetSMPTELineNumber(const ULWord inLineOffset, ULWord &outSMPTELine, bool &outIsField2) const
Answers with the equivalent SMPTE line number for the given line offset into the frame buffer I descr...
Definition: ntv2formatdescriptor.cpp:1168
MAX_ANC_PKTS_PER_RTP_PKT
static const uint32_t MAX_ANC_PKTS_PER_RTP_PKT(0x000000FF)
AJAAncDataLink_A
@ AJAAncDataLink_A
The ancillary data is associated with Link A of the video stream.
Definition: ancillarydata.h:81
AJAAncDataChannel_Both
@ AJAAncDataChannel_Both
SD ONLY – The ancillary data is associated with both the chroma and luma channels.
Definition: ancillarydata.h:132
AJAAncillaryData::U16Packets
std::vector< U16Packet > U16Packets
An ordered sequence of zero or more U16Packet values.
Definition: ancillarydata.h:1062
debug.h
Declares the AJADebug class.
AncChannelSearch_Both
@ AncChannelSearch_Both
Look both luma and chroma samples (SD only)
Definition: ancillarydata.h:156
NTV2Buffer::Set
bool Set(const void *pInUserPointer, const size_t inByteCount)
Sets (or resets) me from a client-supplied address and size.
Definition: ntv2publicinterface.cpp:1614
AJAAncillaryList::SetFromVANCData
static AJAStatus SetFromVANCData(const NTV2Buffer &inFrameBuffer, const NTV2FormatDescriptor &inFormatDesc, AJAAncillaryList &outPackets, const uint32_t inFrameNum=0)
Returns all packets found in the VANC lines of the given NTV2 frame buffer.
Definition: ancillarylist.cpp:880
DECN
#define DECN(__x__, __n__)
Definition: ntv2publicinterface.h:5606
AJAAncDataLoc::GetDataSpace
AJAAncDataSpace GetDataSpace(void) const
Definition: ancillarydata.h:316
AncChannelSearch_Y
@ AncChannelSearch_Y
Only look in luma samples.
Definition: ancillarydata.h:154
AJAAncillaryList::AddReceivedAuxiliaryData
virtual AJAStatus AddReceivedAuxiliaryData(const NTV2Buffer &inReceivedData, const uint32_t inFrameNum=0)
Parse "raw" HDMI auxillary data bytes received from hardware (ingest) into separate AJAAncillaryData ...
Definition: ancillarylist.cpp:667