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