AJA NTV2 SDK  17.5.0.1658
NTV2 SDK 17.5.0.1658
ancillarydata.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2publicinterface.h"
9 #include "ancillarydata.h"
10 #include "ajabase/system/debug.h" // This makes 'ajaanc' dependent upon 'ajabase'
11 #include "ajabase/system/atomic.h"
12 #include "ajabase/system/lock.h"
13 #if defined(AJA_LINUX)
14  #include <string.h> // For memcpy
15  #include <stdlib.h> // For realloc
16 #endif
17 #include <ios>
18 
19 using namespace std;
20 
21 #define LOGGING_ANCDATA AJADebug::IsActive(AJA_DebugUnit_AJAAncData)
22 #define LOGGING_ANC2110RX AJADebug::IsActive(AJA_DebugUnit_Anc2110Rcv)
23 #define LOGGING_ANC2110TX AJADebug::IsActive(AJA_DebugUnit_Anc2110Xmit)
24 
25 #define LOGMYERROR(__x__) {if (LOGGING_ANCDATA) AJA_sERROR (AJA_DebugUnit_AJAAncData, AJAFUNC << ": " << __x__);}
26 #define LOGMYWARN(__x__) {if (LOGGING_ANCDATA) AJA_sWARNING(AJA_DebugUnit_AJAAncData, AJAFUNC << ": " << __x__);}
27 #define LOGMYNOTE(__x__) {if (LOGGING_ANCDATA) AJA_sNOTICE (AJA_DebugUnit_AJAAncData, AJAFUNC << ": " << __x__);}
28 #define LOGMYINFO(__x__) {if (LOGGING_ANCDATA) AJA_sINFO (AJA_DebugUnit_AJAAncData, AJAFUNC << ": " << __x__);}
29 #define LOGMYDEBUG(__x__) {if (LOGGING_ANCDATA) AJA_sDEBUG (AJA_DebugUnit_AJAAncData, AJAFUNC << ": " << __x__);}
30 
31 #define RCV2110ERR(__x__) {if (LOGGING_ANC2110RX) AJA_sERROR (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
32 #define RCV2110WARN(__x__) {if (LOGGING_ANC2110RX) AJA_sWARNING(AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
33 #define RCV2110NOTE(__x__) {if (LOGGING_ANC2110RX) AJA_sNOTICE (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
34 #define RCV2110INFO(__x__) {if (LOGGING_ANC2110RX) AJA_sINFO (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
35 #define RCV2110DBG(__x__) {if (LOGGING_ANC2110RX) AJA_sDEBUG (AJA_DebugUnit_Anc2110Rcv, AJAFUNC << ": " << __x__);}
36 
37 #define XMT2110ERR(__x__) {if (LOGGING_ANC2110TX) AJA_sERROR (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
38 #define XMT2110WARN(__x__) {if (LOGGING_ANC2110TX) AJA_sWARNING(AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
39 #define XMT2110NOTE(__x__) {if (LOGGING_ANC2110TX) AJA_sNOTICE (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
40 #define XMT2110INFO(__x__) {if (LOGGING_ANC2110TX) AJA_sINFO (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
41 #define XMT2110DBG(__x__) {if (LOGGING_ANC2110TX) AJA_sDEBUG (AJA_DebugUnit_Anc2110Xmit, AJAFUNC << ": " << __x__);}
42 
43 #if defined(AJA_WINDOWS)
44  const size_t sENDL(2); // CRLF
45 #else
46  const size_t sENDL(1); // LF
47 #endif
48 
49 // RCV2110DDBG & XMT2110DDBG are for EXTREMELY detailed debug logging:
50 #if 0 // DetailedDebugging
51  #define RCV2110DDBG(__x__) RCV2110DBG(__x__)
52  #define XMT2110DDBG(__x__) XMT2110DBG(__x__)
53 #else
54  #define RCV2110DDBG(__x__)
55  #define XMT2110DDBG(__x__)
56 #endif
57 
58 #if defined(AJAHostIsBigEndian)
59  // Host is BigEndian (BE)
60  #define AJA_ENDIAN_16NtoH(__val__) (__val__)
61  #define AJA_ENDIAN_16HtoN(__val__) (__val__)
62  #define AJA_ENDIAN_32NtoH(__val__) (__val__)
63  #define AJA_ENDIAN_32HtoN(__val__) (__val__)
64  #define AJA_ENDIAN_64NtoH(__val__) (__val__)
65  #define AJA_ENDIAN_64HtoN(__val__) (__val__)
66 #else
67  // Host is LittleEndian (LE)
68  #define AJA_ENDIAN_16NtoH(__val__) AJA_ENDIAN_SWAP16(__val__)
69  #define AJA_ENDIAN_16HtoN(__val__) AJA_ENDIAN_SWAP16(__val__)
70  #define AJA_ENDIAN_32NtoH(__val__) AJA_ENDIAN_SWAP32(__val__)
71  #define AJA_ENDIAN_32HtoN(__val__) AJA_ENDIAN_SWAP32(__val__)
72  #define AJA_ENDIAN_64NtoH(__val__) AJA_ENDIAN_SWAP64(__val__)
73  #define AJA_ENDIAN_64HtoN(__val__) AJA_ENDIAN_SWAP64(__val__)
74 #endif
75 
76 
77 static inline uint32_t ENDIAN_32NtoH(const uint32_t inValue) {return AJA_ENDIAN_32NtoH(inValue);}
78 static inline uint32_t ENDIAN_32HtoN(const uint32_t inValue) {return AJA_ENDIAN_32HtoN(inValue);}
79 
80 
81 const uint32_t AJAAncillaryDataWrapperSize = 7; // 3 bytes header + DID + SID + DC + Checksum: i.e. everything EXCEPT the payload
82 const uint32_t AJAAuxillaryPacketSize = 32; // HDMI Aux packets are always 32 bytes
83 
84 #if defined(_DEBUG)
85  static uint32_t gConstructCount(0); // Number of constructor calls made
86  static uint32_t gDestructCount(0); // Number of destructor calls made
87 #endif // defined(_DEBUG)
88 
89 
90 
91 
93 {
94 #if defined(_DEBUG)
96 #endif // defined(_DEBUG)
97  Init();
98 }
99 
100 
102 {
103 #if defined(_DEBUG)
105 #endif // defined(_DEBUG)
106  Init();
107  *this = inClone;
108 }
109 
110 
112 {
113 #if defined(_DEBUG)
115 #endif // defined(_DEBUG)
116  Init();
117  if (pClone)
118  *this = *pClone;
119 }
120 
121 
123 {
124 #if defined(_DEBUG)
126 #endif // defined(_DEBUG)
127  FreeDataMemory();
128 }
129 
130 
132 {
133  FreeDataMemory(); // reset all internal data to defaults
134 
135  m_DID = 0x00;
136  m_SID = 0x00;
137  m_checksum = 0;
138  m_frameID = 0;
139  m_userData = 0;
140  m_rcvDataValid = false;
141  m_coding = AJAAncDataCoding_Digital;
142  m_ancType = AJAAncDataType_Unknown;
143  m_bufferFmt = AJAAncBufferFormat_Unknown;
144  // Default location:
145  m_location.SetDataLink(AJAAncDataLink_A) // LinkA
146  .SetDataStream(AJAAncDataStream_1) // DS1
147  .SetDataChannel(AJAAncDataChannel_Y) // Y channel
148 // .SetDataSpace(AJAAncDataSpace_VANC) // VANC
149  .SetHorizontalOffset(AJAAncDataHorizOffset_AnyVanc) // VANC
150  .SetLineNumber(AJAAncDataLineNumber_Unknown); // Unknown line number
151 
152  // HDMI Aux specific
153  m_auxType = 0;
154  m_auxHB1 = 0;
155  m_auxHB2 = 0;
156 }
157 
158 
160 {
161  Init();
162 }
163 
164 
166 {
167  return new AJAAncillaryData (this);
168 }
169 
170 
172 {
173  AJAStatus status;
174  FreeDataMemory();
175  try
176  {
177  m_payload.reserve(numBytes);
178  for (uint32_t ndx(0); ndx < numBytes; ndx++)
179  m_payload.push_back(0);
180  status = AJA_STATUS_SUCCESS;
181  }
182  catch(const bad_alloc &)
183  {
184  m_payload.clear();
185  status = AJA_STATUS_MEMORY;
186  }
187  if (AJA_FAILURE(status))
188  LOGMYERROR(::AJAStatusToString(status) << ": Unable to allocate/reserve " << DEC(numBytes) << " bytes");
189  return status;
190 }
191 
192 
194 {
195  m_payload.clear();
196  return AJA_STATUS_SUCCESS;
197 }
198 
199 
200 AJAStatus AJAAncillaryData::SetDID (const uint8_t inDID)
201 {
202  m_DID = inDID;
203  return AJA_STATUS_SUCCESS;
204 }
205 
206 
207 AJAStatus AJAAncillaryData::SetSID (const uint8_t inSID)
208 {
209  m_SID = inSID;
210  return AJA_STATUS_SUCCESS;
211 }
212 
213 AJAStatus AJAAncillaryData::SetChecksum (const uint8_t inChecksum, const bool inValidate)
214 {
215  m_checksum = inChecksum;
216  if (inValidate)
217  if (inChecksum != Calculate8BitChecksum())
218  return AJA_STATUS_FAIL;
219  return AJA_STATUS_SUCCESS;
220 }
221 
222 
223 uint16_t AJAAncillaryData::GetStreamInfo (void) const
224 {
225  if (IS_VALID_AJAAncDataStream(GetLocationDataStream()))
226  return uint16_t(GetLocationDataStream());
227  else if (IS_VALID_AJAAncDataLink(GetLocationVideoLink()))
228  return uint16_t(GetLocationVideoLink());
229  return 0;
230 }
231 
232 
234 {
235  // NOTE: This is NOT the "real" 9-bit checksum used in SMPTE 291 Ancillary packets,
236  // but it's calculated the same way and should be the same as the LS 8-bits
237  // of the 9-bit checksum...
238  uint8_t sum (m_DID);
239  sum += m_SID;
240  sum += uint8_t(m_payload.size());
241  if (!m_payload.empty())
242  for (ByteVector::size_type ndx(0); ndx < m_payload.size(); ndx++)
243  sum += m_payload[ndx];
244 NTV2_ASSERT(sum == uint8_t(Calculate9BitChecksum()));
245  return sum;
246 }
247 
248 
250 {
251  // SMPTE 291-1:2011: 6.7 Checksum Word
252  uint16_t sum (AddEvenParity(m_DID)); // DID
253  sum += AddEvenParity(m_SID); // + SDID
254  sum += AddEvenParity(UByte(GetDC())); // + DC
255  if (!m_payload.empty()) // + payload:
256  for (ByteVector::size_type ndx(0); ndx < m_payload.size(); ndx++)
257  sum += AddEvenParity(m_payload[ndx]);
258 
259  const bool b8 ((sum & 0x100) != 0);
260  const bool b9 (!b8);
261  return (sum & 0x1FF) | (b9 ? 0x200 : 0x000);
262 }
263 
264 
265 //**********
266 // Set anc data location parameters
267 //
269 {
270  AJAStatus status (SetLocationVideoLink(loc.GetDataLink()));
271  if (AJA_SUCCESS(status))
272  status = SetLocationDataStream(loc.GetDataStream());
273  if (AJA_SUCCESS(status))
274  status = SetLocationDataChannel(loc.GetDataChannel());
275  if (AJA_SUCCESS(status))
276  status = SetLocationHorizOffset(loc.GetHorizontalOffset());
277  if (AJA_SUCCESS(status))
278  status = SetLocationLineNumber(loc.GetLineNumber());
279  return status;
280 }
281 
282 
283 //-------------
284 //
286 {
287  if (!IS_VALID_AJAAncDataLink(inLinkValue))
288  return AJA_STATUS_RANGE;
289 
290  m_location.SetDataLink(inLinkValue);
291  return AJA_STATUS_SUCCESS;
292 }
293 
294 
295 //-------------
296 //
298 {
299  if (!IS_VALID_AJAAncDataStream(inStream))
300  return AJA_STATUS_RANGE;
301 
302  m_location.SetDataStream(inStream);
303  return AJA_STATUS_SUCCESS;
304 }
305 
306 
307 //-------------
308 //
310 {
311  if (!IS_VALID_AJAAncDataChannel(inChannel))
312  return AJA_STATUS_RANGE;
313 
314  m_location.SetDataChannel(inChannel);
315  return AJA_STATUS_SUCCESS;
316 }
317 
318 
319 //-------------
320 //
322 {
323  // No range checking here because we don't know how tall the frame is
324  m_location.SetLineNumber(inLineNum);
325  return AJA_STATUS_SUCCESS;
326 }
327 
328 
329 //-------------
330 //
332 {
333  // No range checking here because we don't know how wide the frame is
334  m_location.SetHorizontalOffset(inOffset);
335  return AJA_STATUS_SUCCESS;
336 }
337 
338 //-------------
339 //
341 {
342  if (m_coding != AJAAncDataCoding_Digital && m_coding != AJAAncDataCoding_Raw)
343  return AJA_STATUS_RANGE;
344 
345  m_coding = inCodingType;
346  return AJA_STATUS_SUCCESS;
347 }
348 
349 
350 //**********
351 // Copy payload data from external source to internal storage. Erases current payload memory
352 // (if any) and allocates new memory
353 
354 AJAStatus AJAAncillaryData::SetPayloadData (const uint8_t * pInData, const uint32_t inNumBytes)
355 {
356  if (pInData == NULL || inNumBytes == 0)
357  return AJA_STATUS_NULL;
358 
359  // [Re]Allocate...
360  AJAStatus status (AllocDataMemory(inNumBytes));
361  if (AJA_FAILURE(status))
362  return status;
363 
364  // Copy payload into memory...
365  ::memcpy (&m_payload[0], pInData, inNumBytes);
366  return AJA_STATUS_SUCCESS;
367 }
368 
369 
370 AJAStatus AJAAncillaryData::SetFromSMPTE334 (const uint16_t * pInData, const uint32_t inNumWords, const AJAAncDataLoc & inLocInfo)
371 {
372  if (!pInData)
373  return AJA_STATUS_NULL;
374  if (inNumWords < 7)
375  return AJA_STATUS_RANGE;
376 
377  const uint32_t payloadByteCount (uint32_t(pInData[5] & 0x00FF));
378  if ((inNumWords - 7) > payloadByteCount)
379  return AJA_STATUS_RANGE;
380 
381  // [Re]Allocate...
382  const AJAStatus status (AllocDataMemory(payloadByteCount));
383  if (AJA_FAILURE(status))
384  return status;
385 
386  // Copy payload into new memory...
387  for (uint32_t numWord (0); numWord < payloadByteCount; numWord++)
388  m_payload[numWord] = UByte(pInData[6+numWord] & 0x00FF);
389 
390  SetDataCoding(AJAAncDataCoding_Digital);
391  SetDataLocation(inLocInfo);
392  SetChecksum(UByte(pInData[6+payloadByteCount] & 0x00FF));
393  SetDID(UByte(pInData[3] & 0x00FF));
394  SetSID(UByte(pInData[4] & 0x00FF));
395 
396  return AJA_STATUS_SUCCESS;
397 }
398 
399 
400 //**********
401 // Append payload data from external source to existing internal storage. Realloc's current
402 // payload memory (if any) or allocates new memory
403 
404 AJAStatus AJAAncillaryData::AppendPayloadData (const uint8_t * pInData, const uint32_t inNumBytes)
405 {
406  if (pInData == NULL || inNumBytes == 0)
407  return AJA_STATUS_NULL;
408 
409  try
410  {
411  for (uint32_t ndx(0); ndx < inNumBytes; ndx++)
412  m_payload.push_back(pInData[ndx]);
413  }
414  catch(const bad_alloc &)
415  {
416  return AJA_STATUS_MEMORY;
417  }
418 
419  return AJA_STATUS_SUCCESS;
420 }
421 
422 
423 //**********
424 // Append payload data from an external AJAAncillaryData object to existing internal storage.
425 
427 {
428  try
429  {
430  const uint8_t * pInData (inAnc.GetPayloadData());
431  const uint32_t numBytes (uint32_t(inAnc.GetPayloadByteCount()));
432  for (uint32_t ndx(0); ndx < numBytes; ndx++)
433  m_payload.push_back(pInData[ndx]);
434  }
435  catch(const bad_alloc &)
436  {
437  return AJA_STATUS_MEMORY;
438  }
439 
440  return AJA_STATUS_SUCCESS;
441 }
442 
443 
444 //**********
445 // Copy payload data from internal storage to external destination.
446 
447 AJAStatus AJAAncillaryData::GetPayloadData (uint8_t * pOutData, const uint32_t inNumBytes) const
448 {
449  if (pOutData == NULL)
450  return AJA_STATUS_NULL;
451 
452  if (ByteVectorIndex(inNumBytes) > m_payload.size())
453  return AJA_STATUS_RANGE;
454 
455  ::memcpy (pOutData, GetPayloadData(), inNumBytes);
456  return AJA_STATUS_SUCCESS;
457 }
458 
459 
460 AJAStatus AJAAncillaryData::GetPayloadData (UWordSequence & outUDWs, const bool inAddParity) const
461 {
462  AJAStatus status (AJA_STATUS_SUCCESS);
463  const UWordSequence::size_type origSize (outUDWs.size());
464  for (ByteVectorConstIter iter(m_payload.begin()); iter != m_payload.end() && AJA_SUCCESS(status); ++iter)
465  {
466  const uint16_t UDW (inAddParity ? AddEvenParity(*iter) : *iter);
467  try
468  {
469  outUDWs.push_back(UDW); // Copy 8-bit data into LS 8 bits, add even parity to bit 8, and ~bit 8 to bit 9
470  }
471  catch(...)
472  {
473  status = AJA_STATUS_MEMORY;
474  }
475  } // for each packet byte
476  if (AJA_FAILURE(status))
477  outUDWs.resize(origSize);
478  return status;
479 }
480 
481 
482 uint8_t AJAAncillaryData::GetPayloadByteAtIndex (const uint32_t inIndex0) const
483 {
484  if (ByteVectorIndex(inIndex0) < m_payload.size())
485  return m_payload[inIndex0];
486  else
487  return 0;
488 }
489 
490 
491 AJAStatus AJAAncillaryData::SetPayloadByteAtIndex (const uint8_t inDataByte, const uint32_t inIndex0)
492 {
493  if (inIndex0 >= GetDC())
494  return AJA_STATUS_RANGE;
495 
496  m_payload[inIndex0] = inDataByte;
497  return AJA_STATUS_SUCCESS;
498 }
499 
500 
502 {
503  // should be overridden by derived classes to parse payload data to local data
504  m_rcvDataValid = false;
505 
506  return AJA_STATUS_SUCCESS;
507 }
508 
509 
510 //**********
511 // [Re]Initializes me from the 8-bit GUMP buffer received from extractor (ingest)
513  const size_t inMaxBytes,
514  const AJAAncDataLoc & inLocationInfo,
515  uint32_t & outPacketByteCount)
516 {
517  AJAStatus status = AJA_STATUS_SUCCESS;
518  outPacketByteCount = 0;
519  Clear();
520 
521  // If all is well, pInData points to the beginning of a "GUMP" packet:
522  //
523  // pInData -> 0: 0xFF // 1st byte is always FF
524  // 1: Hdr data1 // location data byte #1
525  // 2: Hdr data2 // location data byte #2
526  // 3: DID // ancillary packet Data ID
527  // 4: SID // ancillary packet Secondary ID (or DBN)
528  // 5: DC // ancillary packet Data Count (size of payload: 0 - 255)
529  // 6: Payload[0] // 1st byte of payload UDW
530  // 7: Payload[1] // 2nd byte of payload UDW
531  // ... ...
532  // (5 + DC): Payload[DC-1] // last byte of payload UDW
533  // (6 + DC): CS (checksum) // 8-bit sum of (DID + SID + DC + Payload[0] + ... + Payload[DC-1])
534  //
535  // (7 + DC): (start of next packet, if any...) returned in packetSize.
536  //
537  // Note that this is the layout of the data as returned from the Anc Extractor hardware, and
538  // is NOT exactly the same as SMPTE-291.
539  //
540  // The inMaxBytes input gives us an indication of how many "valid" bytes remain in the caller's TOTAL
541  // ANC Data buffer. We use this as a sanity check to make sure we don't try to parse past the end
542  // of the captured data.
543  //
544  // The caller provides an AJAAncDataLoc struct with all of the information filled in
545  // except the line number.
546  //
547  // When we have extracted the useful data from the packet, we return the packet size, in bytes, so the
548  // caller can find the start of the next packet (if any).
549 
550  const uint32_t maxBytes(uint32_t(inMaxBytes+0));
551  if (pInData == AJA_NULL)
552  {
553  LOGMYERROR("AJA_STATUS_NULL: NULL pointer");
554  return AJA_STATUS_NULL;
555  }
556 
557  // The minimum size for a packet (i.e. no payload) is 7 bytes
558  if (maxBytes < AJAAncillaryDataWrapperSize)
559  {
560  outPacketByteCount = maxBytes;
561  LOGMYERROR("AJA_STATUS_RANGE: Buffer size " << maxBytes << " smaller than " << AJAAncillaryDataWrapperSize << " bytes");
562  return AJA_STATUS_RANGE;
563  }
564 
565  // The first byte should be 0xFF. If it's not, then the Anc data stream may be broken...
566  if (pInData[0] != 0xFF)
567  {
568  // Let the caller try to resynchronize...
569  LOGMYDEBUG("No data: First GUMP byte is " << xHEX0N(uint16_t(pInData[0]),2) << ", expected 0xFF");
570  return AJA_STATUS_SUCCESS; // Not necessarily an error (no data)
571  }
572 
573  // There are sufficient bytes for a minimum packet, and the first byte is what we expect.
574  // Check the Data Count in this packet...
575  const uint32_t totalBytes (pInData[5] + AJAAncillaryDataWrapperSize);
576 
577  // Does the reported Data Count extend past the end of the buffer?
578  if (totalBytes > maxBytes)
579  {
580  outPacketByteCount = maxBytes;
581  LOGMYERROR("AJA_STATUS_RANGE: Reported packet size " << totalBytes << " [bytes] extends past end of buffer " << inMaxBytes << " by " << (totalBytes-inMaxBytes) << " byte(s)");
582  return AJA_STATUS_RANGE;
583  }
584 
585  // OK... There's enough data in the buffer to contain the packet, and everything else checks out,
586  // so continue parsing the data...
587  m_DID = pInData[3]; // SMPTE-291 Data ID
588  m_SID = pInData[4]; // SMPTE-291 Secondary ID (or DBN)
589  m_checksum = pInData[totalBytes-1]; // Reported checksum
590 
591  // Caller provides all of the "location" information as a default. If the packet header info is "real", overwrite it...
592  m_location = inLocationInfo;
593 
594  if ((pInData[1] & 0x80) != 0)
595  {
596  m_coding = ((pInData[1] & 0x40) == 0) ? AJAAncDataCoding_Digital : AJAAncDataCoding_Raw; // byte 1, bit 6
597  m_location.SetDataStream(AJAAncDataStream_1); // ??? GUMP doesn't tell us the data stream it came from
598  m_location.SetDataChannel(((pInData[1] & 0x20) == 0) ? AJAAncDataChannel_C : AJAAncDataChannel_Y); // byte 1, bit 5
599  m_location.SetDataSpace(((pInData[1] & 0x10) == 0) ? AJAAncDataSpace_VANC : AJAAncDataSpace_HANC); // byte 1, bit 4
600  m_location.SetLineNumber(uint16_t((pInData[1] & 0x0F) << 7) + uint16_t(pInData[2] & 0x7F)); // byte 1, bits 3:0 + byte 2, bits 6:0
601  SetBufferFormat(AJAAncBufferFormat_SDI);
602  //m_location.SetHorizontalOffset(hOffset); // ??? GUMP doesn't report the horiz offset of where the packet started in the raster line
603  }
604 
605  // Allocate space for the payload and copy it in...
606  const uint32_t payloadSize (pInData[5]); // DC: SMPTE-291 Data Count
607  if (payloadSize)
608  {
609  status = AllocDataMemory(payloadSize); // NOTE: This also sets my "DC" value
610  if (AJA_SUCCESS(status))
611  for (uint32_t ndx(0); ndx < payloadSize; ndx++)
612  m_payload[ndx] = pInData[ndx+6];
613  }
614 
615  outPacketByteCount = totalBytes;
616  LOGMYDEBUG("Set from GUMP buffer OK: " << AsString(32));
617  return status;
618 
619 } // InitWithReceivedData
620 
621 //**********
622 // [Re]Initializes me from the buffer received from extractor (ingest)
624  const size_t inMaxBytes,
625  uint32_t & outPacketByteCount)
626 {
627  AJAStatus status = AJA_STATUS_SUCCESS;
628  Clear();
629 
630  // If all is well, pInData points to the beginning of an HDMI Aux packet:
631  //
632  // pInData -> 0: Packet Type // 1st byte is Packet Type / HB0
633  // 1: Header Data1 // location data byte #1
634  // 2: Header Data2 // location data byte #2
635  // 3-32: Payload
636  // ... ...
637  //
638  // Note that this is the layout of the data as returned from the Aux Extractor hardware, and
639  // is NOT exactly the same as the HDMI Specificaiton. (Error checking bytes are omitted)
640  //
641  // The inMaxBytes input gives us an indication of how many "valid" bytes remain in the caller's TOTAL
642  // ANC Data buffer. We use this as a sanity check to make sure we don't try to parse past the end
643  // of the captured data.
644  //
645  // Once the useful data has been copied from the packet buffer, we return the packet size,
646  // in bytes, so the caller can find the start of the next packet (if any).
647 
648  if (pInData == AJA_NULL)
649  {
650  outPacketByteCount = 0;
651  LOGMYERROR("AJA_STATUS_NULL: NULL pointer");
652  return AJA_STATUS_NULL;
653  }
654 
655  // The first byte should be a recognized Aux Packet type.
656  // If it's not, we will assume we are at the end of the valid data
657  if (!AuxPacketTypeIsValid(pInData[0]))
658  {
659  // Let the caller try to resynchronize...
660  outPacketByteCount = 0;
661  LOGMYDEBUG("No data: First Aux byte " << xHEX0N(uint16_t(pInData[0]),2) << " is not a recognized type");
662  return AJA_STATUS_SUCCESS; // Not necessarily an error (no data)
663  }
664 
665  const uint32_t maxBytes(uint32_t(inMaxBytes+0));
666  // The minimum size for a packet (i.e. no payload) is 7 bytes
667  if (maxBytes < AJAAuxillaryPacketSize)
668  {
669  outPacketByteCount = maxBytes;
670  LOGMYERROR("AJA_STATUS_RANGE: Buffer size " << maxBytes << " smaller than " << AJAAuxillaryPacketSize << " bytes");
671  return AJA_STATUS_RANGE;
672  }
673 
674  // There are enough bytes for a minimum packet!
675 
676  const uint32_t totalBytes (AJAAuxillaryPacketSize);
677  // There's enough data in the buffer to contain the packet, and everything else checks out,
678  // so continue parsing the data...
679  m_auxType = pInData[0]; // HDMI Header Byte 0 / Packet Type
680  m_auxHB1 = pInData[1]; // HDMI Header Byte 1 / Header Data 1
681  m_auxHB2 = pInData[2]; // HDMI Header Byte 2 / Header Data 2
682 
683  // HDMI Aux InfoFrames have a checksum and packet length specifier, while other packet types do not
684  m_checksum = 0;
685  uint32_t payloadSize(28); // HDMI Aux Maximum & Default payload
686  int payloadOffset(3); // Packet payload normally starts at 4th byte
687  if (m_auxType & 0x80) // InfoFrame?
688  { // InfoFrames are special:
689  m_checksum = pInData[3]; // InfoFrame checksum is in 4th byte
690  payloadSize = m_auxHB2 & 0x0000001F; // InfoFrame payload size is in LS 5 bits of 3rd byte (HB2)
691  payloadOffset = 4; // InfoFrame payload starts at 5th byte
692  }
693 
694  m_coding = AJAAncDataCoding_Digital;
695  SetBufferFormat(AJAAncBufferFormat_HDMI);
696 
697  // Allocate space for the payload and copy it in...
698  if (payloadSize)
699  {
700  status = AllocDataMemory(payloadSize); // NOTE: This also sets my "DC" value
701  if (AJA_SUCCESS(status))
702  for (uint32_t ndx(0); ndx < payloadSize; ndx++)
703  m_payload[ndx] = pInData[ndx+payloadOffset];
704  }
705 
706  outPacketByteCount = totalBytes;
707  LOGMYDEBUG("Set from HDMI buffer OK: " << AsString(32));
708  return status;
709 
710 } // InitWithReceivedData
711 
713 {
714  uint32_t pktByteCount(0);
715  if (inData.empty())
716  return AJA_STATUS_NULL;
717  return InitWithReceivedData (&inData[0], uint32_t(inData.size()), inLocationInfo, pktByteCount);
718 }
719 
720 
721 //**********
722 // This returns the number of bytes that will be returned by GenerateTransmitData(). This is usually
723 // called first so the caller can allocate a buffer large enough to hold the results.
724 
725 AJAStatus AJAAncillaryData::GetRawPacketSize (uint32_t & outPacketSize) const
726 {
727  outPacketSize = 0;
728 
729  if (m_coding == AJAAncDataCoding_Digital)
730  {
731  // Normal, "digital" ancillary data (i.e. SMPTE-291 based) will have a total size of
732  // seven bytes (3 bytes header + DID + SID + DC + Checksum) plus the payload size...
733  if (GetDC() <= 255)
734  outPacketSize = GetDC() + AJAAncillaryDataWrapperSize;
735  else
736  {
737  // More than 255 bytes of payload is illegal -- return 255 (truncated) to prevent generating a bad GUMP buffer...
738  LOGMYWARN("Illegal packet size " << DEC(GetDC()) << ", exceeds 255 -- returning truncated value (255): " << AsString(32));
739  outPacketSize = 255 + AJAAncillaryDataWrapperSize;
740  }
741  }
742  else if (m_coding == AJAAncDataCoding_Raw)
743  {
744  // Determine how many "packets" are needed to be generated in order to pass all of the payload data (max 255 bytes per packet)...
745  if (!IsEmpty())
746  {
747  // All "analog" packets will have a 255-byte payload, except for the last one...
748  const uint32_t numPackets ((GetDC() + 254) / 255);
749  const uint32_t lastPacketDC (GetDC() % 255);
750 
751  // Each packet has a 7-byte "wrapper" + the payload size...
752  outPacketSize = ((numPackets - 1) * (255 + AJAAncillaryDataWrapperSize)) // All packets except the last one have a payload of 255 bytes
753  + (lastPacketDC + AJAAncillaryDataWrapperSize); // The last packet carries the remainder
754  }
755  }
756  else // huh? (coding not set)
757  return AJA_STATUS_FAIL;
758 
759  return AJA_STATUS_SUCCESS;
760 }
761 
762 
763 //**********
764 // Writes my payload data into the given 8-bit GUMP buffer (playback)
765 
766 AJAStatus AJAAncillaryData::GenerateTransmitData (uint8_t * pData, const size_t inMaxBytes, uint32_t & outPacketSize)
767 {
768  AJAStatus status (GeneratePayloadData());
769 
770  outPacketSize = 0;
771 
772  // Verify that the caller has allocated enough space to hold what's going to be generated
773  uint32_t myPacketSize(0), maxBytes(uint32_t(inMaxBytes+0));
774  GetRawPacketSize(myPacketSize);
775 
776  if (myPacketSize == 0)
777  {
778  LOGMYERROR("AJA_STATUS_FAIL: nothing to do -- raw packet size is zero: " << AsString(32));
779  return AJA_STATUS_FAIL;
780  }
781  if (myPacketSize > maxBytes)
782  {
783  LOGMYERROR("AJA_STATUS_FAIL: " << maxBytes << "-byte client buffer too small to hold " << myPacketSize << " byte(s): " << AsString(32));
784  return AJA_STATUS_FAIL;
785  }
786  if (!IsDigital() && !IsRaw()) // Coding not set: don't generate anything
787  {
788  LOGMYERROR("AJA_STATUS_FAIL: invalid packet coding (neither Raw nor Digital): " << AsString(32));
789  return AJA_STATUS_FAIL;
790  }
791 
792  if (IsDigital())
793  {
794  pData[0] = GetGUMPHeaderByte1();
795  pData[1] = GetGUMPHeaderByte2();
796  pData[2] = GetGUMPHeaderByte3();
797  pData[3] = m_DID;
798  pData[4] = m_SID;
799 
800  uint8_t payloadSize = uint8_t((GetDC() > 255) ? 255 : GetDC()); // Truncate payload to max 255 bytes
801  pData[5] = payloadSize;
802 
803  // Copy payload data to raw stream...
804  status = GetPayloadData(&pData[6], payloadSize);
805 
806  // NOTE: The hardware automatically recalculates the checksum anyway, so this byte
807  // is ignored. However, if the original source had a checksum, we'll send it back...
808  pData[6+payloadSize] = Calculate8BitChecksum();
809 
810  // Done!
811  outPacketSize = myPacketSize;
812  }
813  else if (IsRaw())
814  {
815  // "Analog" or "raw" ancillary data is special in that it may generate multiple output packets,
816  // depending on the length of the payload data.
817  // NOTE: This code assumes that zero-length payloads have already been screened out (in GetRawPacketSize)!
818  const uint32_t numPackets ((GetDC() + 254) / 255);
819 
820  // all packets will have a 255-byte payload except the last one
821  //Note: Unused -- uint32_t lastPacketDC = m_DC % 255;
822 
823  const uint8_t * payloadPtr = GetPayloadData();
824  uint32_t remainingPayloadData = GetDC();
825 
826  for (uint32_t ndx(0); ndx < numPackets; ndx++)
827  {
828  pData[0] = GetGUMPHeaderByte1();
829  pData[1] = GetGUMPHeaderByte2();
830  pData[2] = GetGUMPHeaderByte3();
831  pData[3] = m_DID;
832  pData[4] = m_SID;
833 
834  uint8_t payloadSize = uint8_t((remainingPayloadData > 255) ? 255 : remainingPayloadData); // Truncate payload to max 255 bytes
835  pData[5] = payloadSize; // DC
836 
837  // Copy payload data into GUMP buffer...
838  ::memcpy(&pData[6], payloadPtr, payloadSize);
839 
840  // NOTE: The hardware automatically recalculates the checksum anyway, so this byte
841  // is ignored. However, if the original source had a checksum we'll send it back...
842  pData[6+payloadSize] = m_checksum;
843 
844  // Advance the payloadPtr to the beginning of the next bunch of payload data...
845  payloadPtr += payloadSize;
846 
847  // Decrease the remaining data count...
848  remainingPayloadData -= payloadSize;
849 
850  // Advance the external data stream pointer to the beginning of the next packet...
851  pData += (payloadSize + AJAAncillaryDataWrapperSize);
852  } // for each raw packet
853 
854  outPacketSize = myPacketSize; // Done!
855  } // else if IsRaw
856  LOGMYDEBUG(outPacketSize << " byte(s) generated: " << AsString(32));
857  return status;
858 
859 } // GenerateTransmitData
860 
861 
863 {
864  uint8_t result (0x80); // LE bit is always active
865 
866  if (m_coding == AJAAncDataCoding_Raw)
867  result |= 0x40; // analog/raw (1) or digital (0) ancillary data
868 
869  if (m_location.IsLumaChannel())
870  result |= 0x20; // carried in Y (1) or C stream
871 
872  if (m_location.IsHanc())
873  result |= 0x10;
874 
875  // ms 4 bits of line number
876  result |= (m_location.GetLineNumber() >> 7) & 0x0F; // ms 4 bits [10:7] of line number
877 
878  return result;
879 }
880 
881 
883 {
884  AJAStatus status (GeneratePayloadData());
885  const UWordSequence::size_type origSize (outRawComponents.size());
886 
887  if (IsDigital())
888  {
889  try
890  {
891  const uint8_t dataCount ((GetDC() > 255) ? 255 : uint8_t(GetDC())); // Truncate payload to max 255 bytes
892  outRawComponents.push_back(0x000); // 000
893  outRawComponents.push_back(0x3FF); // 3FF
894  outRawComponents.push_back(0x3FF); // 3FF
895  outRawComponents.push_back(AddEvenParity(GetDID())); // DID
896  outRawComponents.push_back(AddEvenParity(GetSID())); // SDID
897  outRawComponents.push_back(AddEvenParity(dataCount)); // DC
898  }
899  catch(...)
900  {
901  outRawComponents.resize(origSize);
902  status = AJA_STATUS_MEMORY;
903  }
904  }
905 
906  // Copy payload data into output vector...
907  if (AJA_SUCCESS(status))
908  status = GetPayloadData(outRawComponents, IsDigital() /* Add parity for Digital only */); // UDWs
909 
910  // The hardware automatically recalcs the CS, but still needs to be there...
911  if (AJA_SUCCESS(status) && IsDigital())
912  outRawComponents.push_back(Calculate9BitChecksum()); // CS
913 
914  if (AJA_SUCCESS(status))
915  {LOGMYDEBUG((origSize ? "Appended " : "Generated ") << (outRawComponents.size() - origSize) << " UWords from " << AsString(32) << endl << UWordSequence(outRawComponents));}
916  else
917  LOGMYERROR("Failed: " << ::AJAStatusToString(status) << ": origSize=" << origSize << ", " << AsString(32));
918  return status;
919 }
920 
921 
922 // These tables implement the 16-UDWs-per-20-bytes packing cadence:
923 static const size_t gIndexes[] = { 0,1,2,3, 3,4,5,6, 6,7,8,9, 9,10,11,12, 12,13,14,15 };
924 static const unsigned gShifts[] = { 22,12,2,8, 24,14,4,6, 26,16,6,4, 28,18,8,2, 30,20,10,0 };
925 static const uint32_t gMasks[] = { 0xFFC00000, 0x003FF000, 0x00000FFC, 0x00000003,
926  0xFF000000, 0x00FFC000, 0x00003FF0, 0x0000000F,
927  0xFC000000, 0x03FF0000, 0x0000FFC0, 0x0000003F,
928  0xF0000000, 0x0FFC0000, 0x0003FF00, 0x000000FF,
929  0xC0000000, 0x3FF00000, 0x000FFC00, 0x000003FF };
930 
931 
933 {
934  AJAStatus status (GeneratePayloadData());
935  const ULWordSequence::size_type origSize (outData.size());
936  uint32_t u32 (0); // 32-bit value
937 
938  if (!IsDigital())
939  {XMT2110WARN("Analog/raw packet skipped/ignored: " << AsString(32)); return AJA_STATUS_SUCCESS;}
940  if (GetDC() > 255)
941  {XMT2110ERR("Data count exceeds 255: " << AsString(32)); return AJA_STATUS_RANGE;}
942 
944  // Prepare an array of 10-bit DID/SID/DC/UDWs/CS values...
945  const uint16_t did (AddEvenParity(GetDID()));
946  const uint16_t sid (AddEvenParity(GetSID()));
947  const uint16_t dc (AddEvenParity(uint8_t(GetDC())));
948  const uint16_t cs (Calculate9BitChecksum());
949 
950  UWordSequence UDW16s; // 10-bit even-parity words
951  UDW16s.reserve(GetDC()+4); // Reserve DID + SID + DC + UDWs + CS
952  UDW16s.push_back(did);
953  UDW16s.push_back(sid);
954  UDW16s.push_back(dc);
955 
956  // Append 8-bit payload data, converting into 10-bit values with even parity added...
957  status = GetPayloadData(UDW16s, true); // Append 10-bit even-parity UDWs
958  if (AJA_FAILURE(status))
959  {XMT2110ERR("GetPayloadData failed: " << AsString(32)); return status;}
960  UDW16s.push_back(cs); // Checksum is the caboose
961  // Done -- 10-bit DID/SID/DC/UDWs/CS array is prepared
962  XMT2110DBG("From " << UWordSequence(UDW16s) << " " << AsString(32));
964 
965  // Begin writing into "outData" array.
966  // My first 32-bit longword is the Anc packet header, which contains location info...
967  const AJARTPAncPacketHeader pktHdr (GetDataLocation());
968  const uint32_t pktHdrWord (pktHdr.GetULWord());
969  outData.push_back(pktHdrWord);
970 // XMT2110DDBG("outU32s[" << DEC(outData.size()-1) << "]=" << xHEX0N(ENDIAN_32NtoH(pktHdrWord),8) << " (BigEndian)"); // Byte-Swap it to make BigEndian look right
971 
972  // All subsequent 32-bit longwords come from the array of 10-bit values I built earlier.
973  const size_t numUDWs (UDW16s.size());
974  size_t UDWndx (0);
975  u32 = 0;
976  do
977  {
978  for (unsigned loopNdx(0); loopNdx < sizeof(gIndexes) / sizeof(size_t); loopNdx++)
979  {
980  const bool is4th ((loopNdx & 3) == 3);
981  const size_t ndx (UDWndx + gIndexes[loopNdx]);
982  const bool isPastEnd (ndx >= numUDWs);
983  const uint32_t UDW (isPastEnd ? 0 : uint32_t(UDW16s[ndx]));
984  const unsigned shift (gShifts[loopNdx]);
985  const uint32_t mask (gMasks[loopNdx]);
986 // if (!isPastEnd) XMT2110DDBG("u16s[" << DEC(ndx) << "]=" << xHEX0N(UDW,3));
987  if (is4th)
988  {
989  u32 |= (UDW >> shift) & mask;
990  outData.push_back(ENDIAN_32HtoN(u32));
991 // XMT2110DDBG("outU32s[" << DEC(outData.size()-1) << "]=" << xHEX0N(u32,8) << " (BigEndian)");
992  u32 = 0; // Reset, start over
993  if (isPastEnd)
994  break; // Done, 32-bit longword aligned
995  continue;
996  }
997  // Continue building this 32-bit longword...
998  u32 |= (UDW << shift) & mask;
999  } // inner loop
1000  UDWndx += 16;
1001  } while (UDWndx < numUDWs);
1002 
1003  /* The Pattern: (unrolling the above loop): BitCnt ShiftLeft ShiftRight
1004  u32 = (uint32_t(UDW16s.at( 0)) << 22) & 0xFFC00000; // 0b00000|0x00|00: [ 0] all 10 bits 0+10=10 32-10=22
1005  u32 |= (uint32_t(UDW16s.at( 1)) << 12) & 0x003FF000; // 0b00001|0x01|01: [ 1] all 10 bits 10+10=20 22-10=12
1006  u32 |= (uint32_t(UDW16s.at( 2)) << 2) & 0x00000FFC; // 0b00010|0x02|02: [ 2] all 10 bits 20+10=30 12-10=2
1007  u32 |= (uint32_t(UDW16s.at( 3)) >> 8) & 0x00000003; // 0b00011|0x03|03: [ 3] first (MS 2 bits) 30+2=32 10-2=8
1008  outData.push_back(ENDIAN_32HtoN(u32));
1009  u32 = (uint32_t(UDW16s.at( 3)) << 24) & 0xFF000000; // 0b00100|0x04|04: [ 3] last (LS 8 bits) 0+8=8 32-8=24
1010  u32 |= (uint32_t(UDW16s.at( 4)) << 14) & 0x00FFC000; // 0b00101|0x05|05: [ 4] all 10 bits 8+10=18 24-10=14
1011  u32 |= (uint32_t(UDW16s.at( 5)) << 4) & 0x00003FF0; // 0b00110|0x06|06: [ 5] all 10 bits 18+10=28 14-10=4
1012  u32 |= (uint32_t(UDW16s.at( 6)) >> 6) & 0x0000000F; // 0b00111|0x07|07: [ 6] first (MS 4 bits) 28+4=32 10-4=6
1013  outData.push_back(ENDIAN_32HtoN(u32));
1014  u32 = (uint32_t(UDW16s.at( 6)) << 26) & 0xFC000000; // 0b01000|0x08|08: [ 6] last (LS 6 bits) 0+6=6 32-6=26
1015  u32 |= (uint32_t(UDW16s.at( 7)) << 16) & 0x03FF0000; // 0b01001|0x09|09: [ 7] all 10 bits 6+10=16 26-10=16
1016  u32 |= (uint32_t(UDW16s.at( 8)) << 6) & 0x0000FFC0; // 0b01010|0x0A|10: [ 8] all 10 bits 16+10=26 16-10=6
1017  u32 |= (uint32_t(UDW16s.at( 9)) >> 4) & 0x0000003F; // 0b01011|0x0B|11: [ 9] first (MS 6 bits) 26+6=32 10-6=4
1018  outData.push_back(ENDIAN_32HtoN(u32));
1019  u32 = (uint32_t(UDW16s.at( 9)) << 28) & 0xF0000000; // 0b01100|0x0C|12: [ 9] last (LS 4 bits) 0+4=4 32-4=28
1020  u32 |= (uint32_t(UDW16s.at(10)) << 18) & 0x0FFC0000; // 0b01101|0x0D|13: [10] all 10 bits 4+10=14 28-10=18
1021  u32 |= (uint32_t(UDW16s.at(11)) << 8) & 0x0003FF00; // 0b01110|0x0E|14: [11] all 10 bits 14+10=24 18-10=8
1022  u32 |= (uint32_t(UDW16s.at(12)) >> 2) & 0x000000FF; // 0b01111|0x0F|15: [12] first (MS 8 bits) 24+8=32 10-8=2
1023  outData.push_back(ENDIAN_32HtoN(u32));
1024  u32 = (uint32_t(UDW16s.at(12)) << 30) & 0xC0000000; // 0b10000|0x10|16: [12] last (LS 2 bits) 0+2=2 32-2=30
1025  u32 |= (uint32_t(UDW16s.at(13)) << 20) & 0x3FF00000; // 0b10001|0x11|17: [13] all 10 bits 2+10=12 30-10=20
1026  u32 |= (uint32_t(UDW16s.at(14)) << 10) & 0x000FFC00; // 0b10010|0x12|18: [14] all 10 bits 12+10=22 20-10=10
1027  u32 |= (uint32_t(UDW16s.at(15)) >> 0) & 0x000003FF; // 0b10011|0x13|19: [15] all 10 bits 22+10=32 10-10=0
1028  outData.push_back(ENDIAN_32HtoN(u32)); */
1029 
1030 #if defined(_DEBUG)
1031 {
1032  ostringstream oss;
1033  oss << (origSize ? "Appended " : "Generated ") << (outData.size() - origSize) << " U32s:";
1034  for (size_t ndx(origSize); ndx < outData.size(); ndx++) // outData is in Network Byte Order
1035  oss << " " << HEX0N(ENDIAN_32NtoH(outData[ndx]),8); // so byte-swap to make it look right in the log
1036  oss << " BigEndian from " << AsString(32);
1037  XMT2110DBG(oss.str());
1038 }
1039 #else
1040  XMT2110DBG((origSize ? "Appended " : "Generated ")
1041  << (outData.size() - origSize) << " 32-bit words from " << AsString(32));
1042 #endif
1043  return AJA_STATUS_SUCCESS;
1044 } // GenerateTransmitData
1045 
1046 
1047 AJAStatus AJAAncillaryData::InitWithReceivedData (const ULWordSequence & inU32s, uint16_t & inOutU32Ndx, const bool inIgnoreChecksum)
1048 {
1049  const size_t numU32s (inU32s.size());
1050 
1051  Clear(); // Reset me -- start over
1052 
1053  if (inOutU32Ndx >= numU32s)
1054  {RCV2110ERR("Index error: [" << DEC(inOutU32Ndx) << "] past end of [" << DEC(numU32s) << "] element buffer"); return AJA_STATUS_RANGE;}
1055 
1056  AJARTPAncPacketHeader ancPktHeader;
1057  if (!ancPktHeader.ReadFromULWordVector(inU32s, inOutU32Ndx))
1058  {RCV2110ERR("AJARTPAncPacketHeader::ReadFromULWordVector failed at [" << DEC(inOutU32Ndx) << "]"); return AJA_STATUS_FAIL;}
1059 
1060  const AJAAncDataLoc dataLoc (ancPktHeader.AsDataLocation());
1061  RCV2110DDBG("u32=" << xHEX0N(ENDIAN_32NtoH(inU32s.at(inOutU32Ndx)),8) << " inU32s[" << DEC(inOutU32Ndx) << " of " << DEC(numU32s) << "] AncPktHdr: " << ancPktHeader << " -- AncDataLoc: " << dataLoc);
1062 
1063  if (++inOutU32Ndx >= numU32s)
1064  {RCV2110ERR("Index error: [" << DEC(inOutU32Ndx) << "] past end of [" << DEC(numU32s) << "] element buffer"); return AJA_STATUS_RANGE;}
1065 
1066  // Set location info...
1067  AJAStatus result;
1068  result = SetLocationVideoLink(dataLoc.GetDataLink());
1069  if (AJA_FAILURE(result)) {RCV2110ERR("SetLocationVideoLink failed, dataLoc: " << dataLoc); return result;}
1070 
1071  result = SetLocationDataStream(dataLoc.GetDataStream());
1072  if (AJA_FAILURE(result)) {RCV2110ERR("SetLocationDataStream failed, dataLoc: " << dataLoc); return result;}
1073 
1074  result = SetLocationDataChannel(dataLoc.GetDataChannel());
1075  if (AJA_FAILURE(result)) {RCV2110ERR("SetLocationDataChannel failed, dataLoc: " << dataLoc); return result;}
1076 
1077  result = SetLocationHorizOffset(dataLoc.GetHorizontalOffset());
1078  if (AJA_FAILURE(result)) {RCV2110ERR("SetLocationHorizOffset failed, dataLoc: " << dataLoc); return result;}
1079 
1080  result = SetLocationLineNumber(dataLoc.GetLineNumber());
1081  if (AJA_FAILURE(result)) {RCV2110ERR("SetLocationLineNumber failed, dataLoc: " << dataLoc); return result;}
1082 
1083  // Unpack this anc packet...
1084  UWordSequence u16s; // 10-bit even-parity words
1085  bool gotChecksum (false);
1086  size_t dataCount (0);
1087  uint32_t u32 (ENDIAN_32NtoH(inU32s.at(inOutU32Ndx)));
1088  const size_t startU32Ndx (inOutU32Ndx);
1089  RCV2110DDBG("u32=" << xHEX0N(u32,8) << " inU32s[" << DEC(inOutU32Ndx) << " of " << DEC(numU32s) << "]");
1090  do
1091  {
1092  uint16_t u16 (0);
1093  for (unsigned loopNdx(0); loopNdx < 20 && !gotChecksum; loopNdx++)
1094  {
1095  const bool is4th ((loopNdx & 3) == 3);
1096  const bool is1st ((loopNdx & 3) == 0);
1097  const unsigned shift (gShifts[loopNdx]);
1098  const uint32_t mask (gMasks[loopNdx]);
1099  if (is4th)
1100  {
1101  u16 = uint16_t((u32 & mask) << shift);
1102 
1103  // Grab next u32 value...
1104  if (++inOutU32Ndx >= numU32s)
1105  {
1106  u16s.push_back(u16); // RCV2110DDBG("u16s[" << DEC(u16s.size()-1) << "]=" << xHEX0N(u16,3) << " (Past end)");
1107  break; // Past end
1108  }
1109  u32 = ENDIAN_32NtoH(inU32s.at(inOutU32Ndx));
1110  RCV2110DDBG("u32=" << xHEX0N(u32,8) << " inU32s[" << DEC(inOutU32Ndx) << " of " << DEC(numU32s) << "], u16=" << xHEX0N(u16,3)
1111  << " from " << DEC(loopNdx) << "(" << xHEX0N(inU32s.at(inOutU32Ndx-1),8) << " & " << xHEX0N(mask,8) << ") << " << DEC(shift));
1112  if (shift)
1113  continue; // go around
1114  }
1115  else if (is1st)
1116  {
1117 // RCV2110DDBG("u16s[" << DEC(u16s.size()) << "]=" << xHEX0N(u16,3) << " | " << xHEX0N(uint16_t((u32 & mask) >> shift),3)
1118 // << " = " << xHEX0N(u16 | uint16_t((u32 & mask) >> shift),3));
1119  u16 |= uint16_t((u32 & mask) >> shift);
1120  }
1121  else
1122  {
1123  u16 = uint16_t((u32 & mask) >> shift);
1124 // RCV2110DDBG("u16s[" << DEC(u16s.size()) << "]=" << xHEX0N(u16,3));
1125  }
1126  u16s.push_back(u16); // RCV2110DDBG("u16s[" << DEC(u16s.size()-1) << "]=" << xHEX0N(u16,3));
1127  switch(u16s.size())
1128  {
1129  case 1: SetDID(uint8_t(u16)); break; // Got DID
1130  case 2: SetSID(uint8_t(u16)); break; // Got SID
1131  case 3: dataCount = size_t(u16 & 0x0FF); break; // Got DC
1132  default: if (u16s.size() == (dataCount + 4))
1133  {gotChecksum = true; RCV2110DDBG("Got checksum, DC=" << xHEX0N(dataCount,2) << " CS=" << xHEX0N(u16s.back(),3));} // Got CS
1134  break;
1135  }
1136  } // loop 20 times (or until gotChecksum)
1137  if (gotChecksum)
1138  break;
1139  } while (inOutU32Ndx < numU32s);
1140 
1141  if (u16s.size() < 4)
1142  { ostringstream oss;
1143  if (u16s.size() < 1) oss << " NoDID";
1144  else oss << " DID=" << xHEX0N(UWord(GetDID()),2);
1145  if (u16s.size() < 2) oss << " NoSID";
1146  else oss << " SID=" << xHEX0N(UWord(GetSID()),2);
1147  if (u16s.size() < 3) oss << " NoDC";
1148  else oss << " DC=" << DEC(dataCount);
1149  RCV2110ERR("Incomplete/bad packet:" << oss.str() << " NoCS" << " -- only unpacked " << u16s);
1150  return AJA_STATUS_FAIL;
1151  }
1152  RCV2110DBG("Consumed " << DEC(inOutU32Ndx - startU32Ndx + 1) << " ULWord(s), " << (gotChecksum?"":"NoCS, ") << "DC=" << DEC(dataCount) << ", unpacked " << u16s);
1153  if (inOutU32Ndx < numU32s)
1154  inOutU32Ndx++; // Bump to next Anc packet, if any
1155 
1156  // Did we get the whole packet?
1157  if (dataCount > (u16s.size()-3)) // DC > (u16s.size minus DID, SID, DC)?
1158  { // Uh-oh: too few u16s -- someone's pulling our leg
1159  RCV2110ERR("Incomplete/bad packet: " << DEC(u16s.size()) << " U16s, but missing " << DEC(dataCount - (u16s.size()-3))
1160  << " byte(s), expected DC=" << DEC(dataCount) << " -- DID=" << xHEX0N(UWord(GetDID()),2) << " SID=" << xHEX0N(UWord(GetSID()),2));
1161  return AJA_STATUS_FAIL;
1162  }
1163 
1164  // Copy in the Anc packet data, while stripping off parity...
1165  for (size_t ndx(0); ndx < dataCount; ndx++)
1166  m_payload.push_back(uint8_t(u16s.at(ndx+3)));
1167 
1168  result = SetChecksum(uint8_t(u16s.at(u16s.size()-1)), true /*validate*/);
1169  if (AJA_FAILURE(result))
1170  {
1171  if (inIgnoreChecksum)
1172  {RCV2110WARN("SetChecksum=" << xHEX0N(u16s.at(u16s.size()-1),3) << " failed, calculated=" << xHEX0N(Calculate9BitChecksum(),3)); result = AJA_STATUS_SUCCESS;}
1173  else
1174  {RCV2110ERR("SetChecksum=" << xHEX0N(u16s.at(u16s.size()-1),3) << " failed, calculated=" << xHEX0N(Calculate9BitChecksum(),3)); return result;}
1175  }
1176  SetBufferFormat(AJAAncBufferFormat_RTP);
1177  RCV2110DBG(AsString(64));
1178 
1179  /* The Pattern: (unrolling the above loop):
1180  u32 = ENDIAN_32NtoH(inU32s.at(0));
1181  u16 = uint16_t((u32 & 0xFFC00000) >> 22); // all 10 bits 0
1182  u16s.push_back(u16);
1183  u16 = uint16_t((u32 & 0x003FF000) >> 12); // all 10 bits 1
1184  u16s.push_back(u16);
1185  u16 = uint16_t((u32 & 0x00000FFC) >> 2); // all 10 bits 2
1186  u16s.push_back(u16);
1187  u16 = uint16_t((u32 & 0x00000003) << 8); // first (MS 2 bits) 3
1188 
1189  u32 = ENDIAN_32NtoH(inU32s.at(1));
1190  u16 |= uint16_t((u32 & 0xFF000000) >> 24); // last (LS 8 bits) 4
1191  u16s.push_back(u16);
1192  u16 = uint16_t((u32 & 0x00FFC000) >> 14); // all 10 bits 5
1193  u16s.push_back(u16);
1194  u16 = uint16_t((u32 & 0x00003FF0) >> 4); // all 10 bits 6
1195  u16s.push_back(u16);
1196  u16 = uint16_t((u32 & 0x0000000F) << 6); // first (MS 4 bits) 7
1197 
1198  u32 = ENDIAN_32NtoH(inU32s.at(2));
1199  u16 |= uint16_t((u32 & 0xFC000000) >> 26); // last (LS 6 bits) 8
1200  u16s.push_back(u16);
1201  u16 = uint16_t((u32 & 0x03FF0000) >> 16); // all 10 bits 9
1202  u16s.push_back(u16);
1203  u16 = uint16_t((u32 & 0x0000FFC0) >> 6); // all 10 bits 10
1204  u16s.push_back(u16);
1205  u16 = uint16_t((u32 & 0x0000003F) << 4); // first (MS 6 bits) 11
1206 
1207  u32 = ENDIAN_32NtoH(inU32s.at(3));
1208  u16 |= uint16_t((u32 & 0xF0000000) >> 28); // last (LS 4 bits) 12
1209  u16s.push_back(u16);
1210  u16 = uint16_t((u32 & 0x0FFC0000) >> 18); // all 10 bits 13
1211  u16s.push_back(u16);
1212  u16 = uint16_t((u32 & 0x0003FF00) >> 8); // all 10 bits 14
1213  u16s.push_back(u16);
1214  u16 = uint16_t((u32 & 0x000000FF) << 2); // first (MS 8 bits) 15
1215 
1216  u32 = ENDIAN_32NtoH(inU32s.at(4));
1217  u16 |= uint16_t((u32 & 0xC0000000) >> 30); // last (LS 2 bits) 16
1218  u16s.push_back(u16);
1219  u16 = uint16_t((u32 & 0x3FF00000) >> 20); // all 10 bits 17
1220  u16s.push_back(u16);
1221  u16 = uint16_t((u32 & 0x000FFC00) >> 10); // all 10 bits 18
1222  u16s.push_back(u16);
1223  u16 = uint16_t((u32 & 0x000003FF) >> 0); // all 10 bits 19
1224  u16s.push_back(u16);
1225 */
1226  return result;
1227 } // InitWithReceivedData (const ULWordSequence&,uint16_t&)
1228 
1229 
1230 static const string gEmptyString;
1231 
1232 
1233 const string & AJAAncDataLinkToString (const AJAAncDataLink inValue, const bool inCompact)
1234 {
1235  static const string gAncDataLinkToStr [] = {"A", "B", "?"};
1236  static const string gDAncDataLinkToStr [] = {"AJAAncDataLink_A", "AJAAncDataLink_B", "AJAAncDataLink_Unknown"};
1237 
1238  return IS_VALID_AJAAncDataLink(inValue) ? (inCompact ? gAncDataLinkToStr[inValue] : gDAncDataLinkToStr[inValue]) : gAncDataLinkToStr[2];
1239 }
1240 
1241 
1242 const string & AJAAncDataStreamToString (const AJAAncDataStream inValue, const bool inCompact)
1243 {
1244  static const string gAncDataStreamToStr [] = {"DS1", "DS2", "DS3", "DS4", "?"};
1245  static const string gDAncDataStreamToStr [] = {"AJAAncDataStream_1", "AJAAncDataStream_2",
1246  "AJAAncDataStream_3", "AJAAncDataStream_4", "AJAAncDataStream_Unknown"};
1247 
1248  return IS_VALID_AJAAncDataStream(inValue) ? (inCompact ? gAncDataStreamToStr[inValue] : gDAncDataStreamToStr[inValue]) : gEmptyString;
1249 }
1250 
1251 
1252 const string & AJAAncDataChannelToString (const AJAAncDataChannel inValue, const bool inCompact)
1253 {
1254  static const string gAncDataChannelToStr [] = {"C", "Y", "?"};
1255  static const string gDAncDataChannelToStr [] = {"AJAAncDataChannel_C", "AJAAncDataChannel_Y", "AJAAncDataChannel_Unknown"};
1256 
1257  return IS_VALID_AJAAncDataChannel(inValue) ? (inCompact ? gAncDataChannelToStr[inValue] : gDAncDataChannelToStr[inValue]) : gEmptyString;
1258 }
1259 
1260 
1261 const string & AJAAncDataSpaceToString (const AJAAncDataSpace inValue, const bool inCompact)
1262 {
1263  static const string gAncDataSpaceToStr [] = {"VANC", "HANC", "????"};
1264  static const string gDAncDataSpaceToStr [] = {"AJAAncDataSpace_VANC", "AJAAncDataSpace_HANC", "AJAAncDataSpace_Unknown"};
1265 
1266  return IS_VALID_AJAAncDataSpace(inValue) ? (inCompact ? gAncDataSpaceToStr[inValue] : gDAncDataSpaceToStr[inValue]) : gEmptyString;
1267 }
1268 
1269 
1270 string AJAAncLineNumberToString (const uint16_t inValue)
1271 {
1272  ostringstream oss;
1273  if (inValue == AJAAncDataLineNumber_AnyVanc)
1274  oss << "VANC";
1275  else if (inValue == AJAAncDataLineNumber_Anywhere)
1276  oss << "UNSP"; // Unspecified -- anywhere
1277  else if (inValue == AJAAncDataLineNumber_Future)
1278  oss << "OVFL"; // Overflow
1279  else if (inValue == AJAAncDataLineNumber_Unknown)
1280  oss << "UNKN";
1281  else
1282  oss << "L" << DEC(inValue);
1283  return oss.str();
1284 }
1285 
1286 
1287 string AJAAncHorizOffsetToString (const uint16_t inValue)
1288 {
1289  ostringstream oss;
1290  if (inValue == AJAAncDataHorizOffset_AnyHanc)
1291  oss << "HANC";
1292  else if (inValue == AJAAncDataHorizOffset_AnyVanc)
1293  oss << "VANC";
1294  else if (inValue == AJAAncDataHorizOffset_Anywhere)
1295  oss << "UNSP";
1296  else if (inValue == AJAAncDataHorizOffset_Future)
1297  oss << "OVFL";
1298  else if (inValue == AJAAncDataHorizOffset_Unknown)
1299  oss << "UNKN";
1300  else
1301  oss << "+" << DEC(inValue);
1302  return oss.str();
1303 }
1304 
1305 
1306 ostream & AJAAncDataLoc::Print (ostream & oss, const bool inCompact) const
1307 {
1308  oss << ::AJAAncDataLinkToString(GetDataLink(), inCompact)
1309  << "|" << ::AJAAncDataStreamToString(GetDataStream(), inCompact)
1310  << "|" << ::AJAAncDataChannelToString(GetDataChannel(), inCompact)
1311  << "|" << ::AJAAncLineNumberToString(GetLineNumber())
1312  << "|" << ::AJAAncHorizOffsetToString(GetHorizontalOffset());
1313  return oss;
1314 }
1315 
1317 {
1318  // Everything must match exactly:
1319  if (GetDataLink() != inRHS.GetDataLink())
1320  return AJA_STATUS_FAIL;
1321  if (GetDataStream() != inRHS.GetDataStream())
1322  return AJA_STATUS_FAIL;
1323  if (GetDataChannel() != inRHS.GetDataChannel())
1324  return AJA_STATUS_FAIL;
1325 // if (GetDataSpace() == inRHS.GetDataSpace()) // No longer necessary
1326 // return AJA_STATUS_FAIL;
1327  if (GetLineNumber() != inRHS.GetLineNumber())
1328  return AJA_STATUS_FAIL;
1329  if (GetHorizontalOffset() && inRHS.GetHorizontalOffset())
1330  if (GetHorizontalOffset() != inRHS.GetHorizontalOffset())
1331  return AJA_STATUS_FAIL;
1332  return AJA_STATUS_SUCCESS;
1333 }
1334 
1335 string AJAAncDataLoc::CompareWithInfo (const AJAAncDataLoc & inRHS) const
1336 {
1337  ostringstream oss;
1338  if (GetDataLink() != inRHS.GetDataLink())
1339  oss << ", Link " << ::AJAAncDataLinkToString(GetDataLink()) << " != " << ::AJAAncDataLinkToString(inRHS.GetDataLink());
1340  if (GetDataStream() != inRHS.GetDataStream())
1341  oss << ", " << ::AJAAncDataStreamToString(GetDataStream()) << " != " << ::AJAAncDataStreamToString(inRHS.GetDataStream());
1342  if (GetDataChannel() != inRHS.GetDataChannel())
1343  oss << ", Data Channel " << ::AJAAncDataChannelToString(GetDataChannel()) << " != " << ::AJAAncDataChannelToString(inRHS.GetDataChannel());
1344 // if (GetDataSpace() == inRHS.GetDataSpace()) // No longer necessary
1345 // oss << ", " << ::AJAAncDataSpaceToString(GetDataSpace()) << " != " << ::AJAAncDataSpaceToString(inRHS.GetDataSpace());
1346  if (GetLineNumber() != inRHS.GetLineNumber())
1347  oss << ", " << "Line " << DEC(GetLineNumber()) << " != " << DEC(inRHS.GetLineNumber());
1348  if (GetHorizontalOffset() && inRHS.GetHorizontalOffset())
1349  if (GetHorizontalOffset() != inRHS.GetHorizontalOffset())
1350  oss << ", " << "HOffset " << DEC(GetHorizontalOffset()) << " != " << DEC(inRHS.GetHorizontalOffset());
1351 
1352  if (oss.str().length() > 2)
1353  return oss.str().substr(2, oss.str().length() - 2); // remove first ", "
1354  return string();
1355 }
1356 
1357 
1358 string AJAAncDataLocToString (const AJAAncDataLoc & inValue, const bool inCompact)
1359 {
1360  ostringstream oss;
1361  inValue.Print(oss, inCompact);
1362  return oss.str();
1363 }
1364 
1365 ostream & operator << (ostream & inOutStream, const AJAAncDataLoc & inValue)
1366 {
1367  return inValue.Print(inOutStream, true);
1368 }
1369 
1370 
1371 const string & AJAAncDataCodingToString (const AJAAncDataCoding inValue, const bool inCompact)
1372 {
1373  static const string gAncDataCodingToStr [] = {"Dig", "Ana", "???"};
1374  static const string gDAncDataCodingToStr [] = {"AJAAncDataCoding_Digital", "AJAAncDataCoding_Raw", "AJAAncDataCoding_Unknown"};
1375 
1376  return IS_VALID_AJAAncDataCoding(inValue) ? (inCompact ? gAncDataCodingToStr[inValue] : gDAncDataCodingToStr[inValue]) : gEmptyString;
1377 }
1378 
1379 
1380 const string & AJAAncBufferFormatToString (const AJAAncBufferFormat inValue, const bool inCompact)
1381 {
1382  static const string gAncBufFmtToStr [] = {"UNK", "FBVANC", "SDI", "RTP", "HDMI", ""};
1383  static const string gDAncBufFmtToStr [] = {"AJAAncBufferFormat_Unknown", "AJAAncBufferFormat_FBVANC",
1384  "AJAAncBufferFormat_SDI", "AJAAncBufferFormat_RTP","AJAAncBufferFormat_HDMI", ""};
1385 
1386  return IS_VALID_AJAAncBufferFormat(inValue) ? (inCompact ? gAncBufFmtToStr[inValue] : gDAncBufFmtToStr[inValue]) : gEmptyString;
1387 }
1388 
1389 
1390 const string & AJAAncDataTypeToString (const AJAAncDataType inValue, const bool inCompact)
1391 {
1392  static const string gAncDataTypeToStr [] = { "Unknown", "SMPTE 2016-3 AFD", "SMPTE 12-M RP188", "SMPTE 12-M VITC",
1393  "SMPTE 334 CEA708", "SMPTE 334 CEA608", "CEA608 Line21", "SMPTE 352 VPID",
1394  "SMPTE 2051 2 Frame Marker", "524D Frame Status", "5251 Frame Status",
1395  "HDR SDR", "HDR10", "HDR HLG", "HDMI Aux", "?"};
1396 
1397  static const string gDAncDataTypeToStr [] = { "AJAAncDataType_Unknown", "AJAAncDataType_Smpte2016_3", "AJAAncDataType_Timecode_ATC",
1398  "AJAAncDataType_Timecode_VITC", "AJAAncDataType_Cea708", "AJAAncDataType_Cea608_Vanc",
1399  "AJAAncDataType_Cea608_Line21", "AJAAncDataType_Smpte352", "AJAAncDataType_Smpte2051",
1400  "AJAAncDataType_FrameStatusInfo524D", "AJAAncDataType_FrameStatusInfo5251",
1401  "AJAAncDataType_HDR_SDR", "AJAAncDataType_HDR_HDR10", "AJAAncDataType_HDR_HLG",
1402  "AJAAncDataType_HDMI_Aux", "?"};
1403 
1404  return inValue < AJAAncDataType_Size ? (inCompact ? gAncDataTypeToStr[inValue] : gDAncDataTypeToStr[inValue]) : gEmptyString;
1405 }
1406 
1407 
1408 ostream & AJAAncillaryData::Print (ostream & oss, const bool inDumpPayload) const
1409 {
1410  oss << "Type:\t\t" << IDAsString() << endl;
1411  if (!IsHDMI())
1412  oss << "DID:\t\t" << xHEX0N(uint32_t(GetDID()),2) << endl
1413  << "SID:\t\t" << xHEX0N(uint32_t(GetSID()),2) << endl;
1414  oss << "DC:\t\t" << DEC(GetDC()) << endl;
1415  if (!IsHDMI())
1416  oss << "CS:\t\t" << xHEX0N(uint32_t(m_checksum),2) << endl
1417  << "Loc:\t\t" << GetDataLocation() << endl;
1418  oss << "Coding:\t\t" << ::AJAAncDataCodingToString(m_coding) << endl
1419  << "Frame:\t\t" << xHEX0N(GetFrameID(),8) << endl
1420  << "Format:\t\t" << ::AJAAncBufferFormatToString(GetBufferFormat()) << endl
1421  << "Valid:\t\t" << (GotValidReceiveData() ? "Yes" : "No");
1422  if (inDumpPayload)
1423  {oss << endl; DumpPayload(oss);}
1424  return oss;
1425 }
1426 
1427 string AJAAncillaryData::IDAsString (void) const
1428 {
1429  ostringstream oss;
1430  if (IsRaw())
1431  oss << "Analog/Raw Line " << DEC(GetDataLocation().GetLineNumber()) << " Packet";
1432  else if (IsHDMI())
1433  oss << AuxPacketTypeToString(GetAuxType());
1434  else
1435  oss << DIDSIDToString(GetDID(), GetSID());
1436  return oss.str();
1437 }
1438 
1439 string AJAAncillaryData::AsString (const uint16_t inMaxBytes) const
1440 {
1441  ostringstream oss;
1442  oss << "[" << ::AJAAncDataCodingToString(GetDataCoding());
1443  if (IsHDMI())
1444  oss << "|" << xHEX0N(uint16_t(GetAuxType()),2)
1445  << HEX0N(uint16_t(GetAuxHB1()),2)
1446  << HEX0N(uint16_t(GetAuxHB2()),2);
1447  else
1448  oss << "|" << ::AJAAncDataLocToString(GetDataLocation())
1449  << "|" << GetDIDSIDPair() << "|CS" << HEX0N(uint16_t(GetChecksum()),2);
1450  oss << "|DC=" << DEC(GetDC());
1451  if (m_frameID)
1452  oss << "|FRx" << HEX0N(GetFrameID(),8);
1453  if (IS_KNOWN_AJAAncBufferFormat(m_bufferFmt))
1454  oss << "|" << ::AJAAncBufferFormatToString(GetBufferFormat());
1455  const string typeStr (IsHDMI() ? AuxPacketTypeToString(GetAuxType())
1456  : DIDSIDToString(GetDID(), GetSID()));
1457  if (!typeStr.empty())
1458  oss << "|" << typeStr;
1459  oss << "]";
1460  if (inMaxBytes && GetDC())
1461  {
1462  uint16_t bytesToDump = uint16_t(GetDC());
1463  oss << ": ";
1464  if (inMaxBytes < bytesToDump)
1465  bytesToDump = inMaxBytes;
1466  for (uint16_t ndx(0); ndx < bytesToDump; ndx++)
1467  oss << HEX0N(uint16_t(m_payload[ndx]),2);
1468  if (bytesToDump < uint16_t(GetDC()))
1469  oss << "..."; // Indicate dump was truncated
1470  }
1471  return oss.str();
1472 }
1473 
1474 ostream & operator << (ostream & inOutStream, const AJAAncDIDSIDPair & inData)
1475 {
1476  inOutStream << "x" << HEX0N(uint16_t(inData.first), 2) << "x" << HEX0N(uint16_t(inData.second), 2);
1477  return inOutStream;
1478 }
1479 
1480 ostream & AJAAncillaryData::DumpPayload (ostream & inOutStream) const
1481 {
1482  if (IsEmpty())
1483  inOutStream << "(NULL payload)" << endl;
1484  else
1485  {
1486  const int32_t kBytesPerLine (32);
1487  uint32_t count (GetDC());
1488  const uint8_t * pData (GetPayloadData());
1489 
1490  while (count)
1491  {
1492  const uint32_t numBytes ((count >= kBytesPerLine) ? kBytesPerLine : count);
1493  inOutStream << ((count == GetDC()) ? "Payload: " : " ");
1494  for (uint8_t num(0); num < numBytes; num++)
1495  {
1496  inOutStream << " " << HEX0N(uint32_t(pData[num]),2);
1497  if (num % 4 == 3)
1498  inOutStream << " "; // an extra space every four bytes for readability
1499  }
1500  inOutStream << endl;
1501  pData += numBytes;
1502  count -= numBytes;
1503  } // loop til break
1504  }
1505  return inOutStream;
1506 }
1507 
1508 
1509 AJAStatus AJAAncillaryData::Compare (const AJAAncillaryData & inRHS, const bool inIgnoreLocation, const bool inIgnoreChecksum) const
1510 {
1511  if (GetDID() != inRHS.GetDID())
1512  return AJA_STATUS_FAIL;
1513  if (GetSID() != inRHS.GetSID())
1514  return AJA_STATUS_FAIL;
1515  if (GetDC() != inRHS.GetDC())
1516  return AJA_STATUS_FAIL;
1517 
1518  if (!inIgnoreChecksum)
1519  if (GetChecksum() != inRHS.GetChecksum())
1520  return AJA_STATUS_FAIL;
1521  if (!inIgnoreLocation)
1522  if (AJA_FAILURE(GetDataLocation().Compare(inRHS.GetDataLocation())))
1523  return AJA_STATUS_FAIL;
1524 
1525  if (GetDataCoding() != inRHS.GetDataCoding())
1526  return AJA_STATUS_FAIL;
1527 
1528  if (!IsEmpty())
1529  if (m_payload != inRHS.m_payload)
1530  return AJA_STATUS_FAIL;
1531 
1532  return AJA_STATUS_SUCCESS;
1533 }
1534 
1535 
1536 string AJAAncillaryData::CompareWithInfo (const AJAAncillaryData & inRHS, const bool inIgnoreLocation, const bool inIgnoreChecksum) const
1537 {
1538  ostringstream oss;
1539  if (GetDID() != inRHS.GetDID())
1540  oss << endl << "DID mismatch: " << xHEX0N(uint16_t(GetDID()),2) << " != " << xHEX0N(uint16_t(inRHS.GetDID()),2);
1541  if (GetSID() != inRHS.GetSID())
1542  oss << endl << "SID mismatch: " << xHEX0N(uint16_t(GetSID()),2) << " != " << xHEX0N(uint16_t(inRHS.GetSID()),2);
1543  if (GetDC() != inRHS.GetDC())
1544  oss << endl << "DC mismatch: " << xHEX0N(GetDC(),4) << " != " << xHEX0N(inRHS.GetDC(),4);
1545 
1546  if (!inIgnoreChecksum)
1547  if (GetChecksum() != inRHS.GetChecksum())
1548  oss << endl << "CS mismatch: " << xHEX0N(uint16_t(GetChecksum()),2) << " != " << xHEX0N(uint16_t(inRHS.GetChecksum()),2);
1549  if (!inIgnoreLocation)
1550  { const string info(GetDataLocation().CompareWithInfo(inRHS.GetDataLocation()));
1551  if (!info.empty())
1552  oss << endl << "Location mismatch: " << info;
1553  }
1554 
1555  if (GetDataCoding() != inRHS.GetDataCoding())
1556  oss << endl << "DataCoding mismatch: " << AJAAncDataCodingToString(GetDataCoding()) << " != " << AJAAncDataCodingToString(inRHS.GetDataCoding());
1557 
1558  if (!IsEmpty())
1559  {
1560  const uint8_t *pLHS(GetPayloadData()), *pRHS(inRHS.GetPayloadData());
1561  ULWordSequence diffNdxs;
1562  for (size_t ndx(0); ndx < GetPayloadByteCount(); ndx++)
1563  if (pLHS[ndx] != pRHS[ndx])
1564  diffNdxs.push_back(ULWord(ndx));
1565  if (!diffNdxs.empty())
1566  oss << endl << DEC(diffNdxs.size()) << " of " << DEC(GetDC()) << " (" << fDEC(100.0*double(diffNdxs.size())/double(GetDC()), 5, 2)
1567  << "%) mismatched payload bytes, starting at offset " << DEC(diffNdxs.at(0));
1568  }
1569 
1570  if (oss.str().length() > sENDL)
1571  return oss.str().substr(sENDL, oss.str().length() - sENDL); // remove leading newline
1572  return string();
1573 }
1574 
1576 {
1577  if (this != &inRHS)
1578  {
1579  m_DID = inRHS.m_DID;
1580  m_SID = inRHS.m_SID;
1581  m_checksum = inRHS.m_checksum;
1582  m_location = inRHS.m_location;
1583  m_coding = inRHS.m_coding;
1584  m_payload = inRHS.m_payload;
1585  m_rcvDataValid = inRHS.m_rcvDataValid;
1586  m_ancType = inRHS.m_ancType;
1587  m_bufferFmt = inRHS.m_bufferFmt;
1588  m_frameID = inRHS.m_frameID;
1589  m_userData = inRHS.m_userData;
1590 
1591  // HDMI Aux specific
1592  m_auxType = inRHS.m_auxType;
1593  m_auxHB1 = inRHS.m_auxHB1;
1594  m_auxHB2 = inRHS.m_auxHB2;
1595  }
1596  return *this;
1597 }
1598 
1600 {
1601  return AJA_SUCCESS(Compare(inRHS, false/*ignoreLocations*/, false/*ignoreChecksums*/));
1602 }
1603 
1604 
1605 // Returns the original data byte in bits 7:0, plus even parity in bit 8 and ~bit 8 in bit 9
1606 uint16_t AJAAncillaryData::AddEvenParity (const uint8_t inDataByte)
1607 {
1608  // Parity Table
1609  static const uint16_t gEvenParityTable[256] =
1610  {
1611  /* 0-7 */ 0x200,0x101,0x102,0x203,0x104,0x205,0x206,0x107,
1612  /* 8-15 */ 0x108,0x209,0x20A,0x10B,0x20C,0x10D,0x10E,0x20F,
1613  /* 16-23 */ 0x110,0x211,0x212,0x113,0x214,0x115,0x116,0x217,
1614  /* 24-31 */ 0x218,0x119,0x11A,0x21B,0x11C,0x21D,0x21E,0x11F,
1615  /* 32-39 */ 0x120,0x221,0x222,0x123,0x224,0x125,0x126,0x227,
1616  /* 40-47 */ 0x228,0x129,0x12A,0x22B,0x12C,0x22D,0x22E,0x12F,
1617  /* 48-55 */ 0x230,0x131,0x132,0x233,0x134,0x235,0x236,0x137,
1618  /* 56-63 */ 0x138,0x239,0x23A,0x13B,0x23C,0x13D,0x13E,0x23F,
1619  /* 64-71 */ 0x140,0x241,0x242,0x143,0x244,0x145,0x146,0x247,
1620  /* 72-79 */ 0x248,0x149,0x14A,0x24B,0x14C,0x24D,0x24E,0x14F,
1621  /* 80-87 */ 0x250,0x151,0x152,0x253,0x154,0x255,0x256,0x157,
1622  /* 88-95 */ 0x158,0x259,0x25A,0x15B,0x25C,0x15D,0x15E,0x25F,
1623  /* 96-103 */ 0x260,0x161,0x162,0x263,0x164,0x265,0x266,0x167,
1624  /* 104-111 */ 0x168,0x269,0x26A,0x16B,0x26C,0x16D,0x16E,0x26F,
1625  /* 112-119 */ 0x170,0x271,0x272,0x173,0x274,0x175,0x176,0x277,
1626  /* 120-127 */ 0x278,0x179,0x17A,0x27B,0x17C,0x27D,0x27E,0x17F,
1627  /* 128-135 */ 0x180,0x281,0x282,0x183,0x284,0x185,0x186,0x287,
1628  /* 136-143 */ 0x288,0x189,0x18A,0x28B,0x18C,0x28D,0x28E,0x18F,
1629  /* 144-151 */ 0x290,0x191,0x192,0x293,0x194,0x295,0x296,0x197,
1630  /* 152-159 */ 0x198,0x299,0x29A,0x19B,0x29C,0x19D,0x19E,0x29F,
1631  /* 160-167 */ 0x2A0,0x1A1,0x1A2,0x2A3,0x1A4,0x2A5,0x2A6,0x1A7,
1632  /* 168-175 */ 0x1A8,0x2A9,0x2AA,0x1AB,0x2AC,0x1AD,0x1AE,0x2AF,
1633  /* 176-183 */ 0x1B0,0x2B1,0x2B2,0x1B3,0x2B4,0x1B5,0x1B6,0x2B7,
1634  /* 184-191 */ 0x2B8,0x1B9,0x1BA,0x2BB,0x1BC,0x2BD,0x2BE,0x1BF,
1635  /* 192-199 */ 0x2C0,0x1C1,0x1C2,0x2C3,0x1C4,0x2C5,0x2C6,0x1C7,
1636  /* 200-207 */ 0x1C8,0x2C9,0x2CA,0x1CB,0x2CC,0x1CD,0x1CE,0x2CF,
1637  /* 208-215 */ 0x1D0,0x2D1,0x2D2,0x1D3,0x2D4,0x1D5,0x1D6,0x2D7,
1638  /* 216-223 */ 0x2D8,0x1D9,0x1DA,0x2DB,0x1DC,0x2DD,0x2DE,0x1DF,
1639  /* 224-231 */ 0x1E0,0x2E1,0x2E2,0x1E3,0x2E4,0x1E5,0x1E6,0x2E7,
1640  /* 232-239 */ 0x2E8,0x1E9,0x1EA,0x2EB,0x1EC,0x2ED,0x2EE,0x1EF,
1641  /* 240-247 */ 0x2F0,0x1F1,0x1F2,0x2F3,0x1F4,0x2F5,0x2F6,0x1F7,
1642  /* 248-255 */ 0x1F8,0x2F9,0x2FA,0x1FB,0x2FC,0x1FD,0x1FE,0x2FF
1643  }; // gEvenParityTable
1644  return gEvenParityTable[inDataByte];
1645 }
1646 
1647 
1648 string AncChannelSearchSelectToString (const AncChannelSearchSelect inSelect, const bool inCompact)
1649 {
1650  switch (inSelect)
1651  {
1652  case AncChannelSearch_Y: return inCompact ? "Y" : "AncChannelSearch_Y";
1653  case AncChannelSearch_C: return inCompact ? "C" : "AncChannelSearch_C";
1654  case AncChannelSearch_Both: return inCompact ? "Y+C" : "AncChannelSearch_Both";
1655  default: break;
1656  }
1657  return "";
1658 }
1659 
1660 
1662  const uint16_t inStartIndex,
1663  const uint16_t inTotalCount,
1664  const uint16_t inIncrement = 2)
1665 {
1666  bool bErr (false);
1667  UWord ndx (0);
1668  if (inIncrement == 0 || inIncrement > 2)
1669  return true; // Increment must be 1 or 2
1670 
1671  // Check parity on all words...
1672  for (ndx = 3; ndx < inTotalCount - 1; ndx++) // Skip ANC Data Flags and Checksum
1673  {
1674  const UWord wordValue (inYUV16Line[inStartIndex + ndx * inIncrement]);
1675  if (wordValue != AJAAncillaryData::AddEvenParity(wordValue & 0xFF))
1676  {
1677  LOGMYERROR ("Parity error at word " << ndx << ": got " << xHEX0N(wordValue,2)
1678  << ", expected " << xHEX0N(AJAAncillaryData::AddEvenParity(wordValue & 0xFF),2));
1679  bErr = true;
1680  }
1681  }
1682 
1683  // The checksum word is different: bit 8 is part of the checksum total, and bit 9 should be ~bit 8...
1684  const UWord checksum (inYUV16Line [inStartIndex + (inTotalCount - 1) * inIncrement]);
1685  const bool b8 ((checksum & BIT(8)) != 0);
1686  const bool b9 ((checksum & BIT(9)) != 0);
1687  if (b8 == b9)
1688  {
1689  LOGMYERROR ("Checksum word error: got " << xHEX0N(checksum,2) << ", expected " << xHEX0N(checksum ^ 0x200, 2));
1690  bErr = true;
1691  }
1692 
1693  // Check the checksum math...
1694  UWord sum (0);
1695  for (ndx = 3; ndx < inTotalCount - 1; ndx++)
1696  sum += inYUV16Line [inStartIndex + ndx * inIncrement] & 0x1FF;
1697 
1698  if ((sum & 0x1FF) != (checksum & 0x1FF))
1699  {
1700  LOGMYERROR ("Checksum math error: got " << xHEX0N(checksum & 0x1FF, 2) << ", expected " << xHEX0N(sum & 0x1FF, 2));
1701  bErr = true;
1702  }
1703 
1704  return bErr;
1705 
1706 } // CheckAncParityAndChecksum
1707 
1708 
1710  const AncChannelSearchSelect inChanSelect,
1711  U16Packets & outRawPackets,
1712  UWordSequence & outWordOffsets)
1713 {
1714  const UWord wordCountMax (UWord(inYUV16Line.size ()));
1715 
1716  // If we're only looking at Y samples, start the search 1 word into the line...
1717  const UWord searchOffset (inChanSelect == AncChannelSearch_Y ? 1 : 0);
1718 
1719  // If we're looking in both channels (e.g. SD video), increment search words by 1, else skip at every other word...
1720  const UWord searchIncr (inChanSelect == AncChannelSearch_Both ? 1 : 2);
1721 
1722  outRawPackets.clear();
1723  outWordOffsets.clear();
1724 
1725  if (!IS_VALID_AncChannelSearchSelect(inChanSelect))
1726  {LOGMYERROR("Bad search select value " << DEC(inChanSelect)); return false;} // bad search select
1727  if (wordCountMax < 12)
1728  {LOGMYERROR("UWordSequence size " << DEC(wordCountMax) << " too small"); return false;} // too small
1729 
1730  for (UWord wordNum = searchOffset; wordNum < (wordCountMax - 12); wordNum += searchIncr)
1731  {
1732  const UWord ancHdr0 (inYUV16Line.at (wordNum + (0 * searchIncr))); // 0x000
1733  const UWord ancHdr1 (inYUV16Line.at (wordNum + (1 * searchIncr))); // 0x3ff
1734  const UWord ancHdr2 (inYUV16Line.at (wordNum + (2 * searchIncr))); // 0x3ff
1735  const UWord ancHdr3 (inYUV16Line.at (wordNum + (3 * searchIncr))); // DID
1736  const UWord ancHdr4 (inYUV16Line.at (wordNum + (4 * searchIncr))); // SDID
1737  const UWord ancHdr5 (inYUV16Line.at (wordNum + (5 * searchIncr))); // DC
1738  if (ancHdr0 == 0x000 && ancHdr1 == 0x3ff && ancHdr2 == 0x3ff)
1739  {
1740  // Total words in ANC packet: 6 header words + data count + checksum word...
1741  UWord dataCount (ancHdr5 & 0xFF);
1742  UWord totalCount (6 + dataCount + 1);
1743 
1744  if (totalCount > wordCountMax)
1745  {
1746  totalCount = wordCountMax;
1747  LOGMYERROR ("packet totalCount " << totalCount << " exceeds max " << wordCountMax);
1748  return false;
1749  }
1750 
1751  // Be sure we don't go past the end of the line buffer...
1752  if (ULWord (wordNum + totalCount) >= wordCountMax)
1753  {
1754  LOGMYDEBUG ("past end of line: " << wordNum << " + " << totalCount << " >= " << wordCountMax);
1755  return false; // Past end of line buffer
1756  }
1757 
1758  if (CheckAncParityAndChecksum (inYUV16Line, wordNum, totalCount, searchIncr))
1759  return false; // Parity/Checksum error
1760 
1761  U16Packet packet;
1762  for (unsigned i = 0; i < totalCount; i++)
1763  packet.push_back (inYUV16Line.at (wordNum + (i * searchIncr)));
1764  outRawPackets.push_back (packet);
1765  outWordOffsets.push_back (wordNum);
1766 
1767  LOGMYINFO ("Found ANC packet in " << ::AncChannelSearchSelectToString(inChanSelect)
1768  << ": DID=" << xHEX0N(ancHdr3,4)
1769  << " SDID=" << xHEX0N(ancHdr4,4)
1770  << " word=" << wordNum
1771  << " DC=" << ancHdr5
1772  << " pix=" << (wordNum / searchIncr));
1773  } // if ANC packet found (wildcard or matching DID/SDID)
1774  } // scan the line
1775 
1776  return true;
1777 
1778 } // GetAncPacketsFromVANCLine
1779 
1780 
1782  UWordSequence & outU16YUVLine,
1783  const uint32_t inNumPixels)
1784 {
1785  const UByte * pInYUV8Buffer (reinterpret_cast <const UByte *> (pInYUV8Line));
1786  const ULWord maxOutElements (inNumPixels * 2);
1787 
1788  outU16YUVLine.clear ();
1789  outU16YUVLine.reserve (maxOutElements);
1790  while (outU16YUVLine.size() < size_t(maxOutElements))
1791  outU16YUVLine.push_back(0);
1792 
1793  if (!pInYUV8Buffer)
1794  {LOGMYERROR("NULL/empty YUV8 buffer"); return false;} // NULL pointer
1795  if (inNumPixels < 12)
1796  {LOGMYERROR("width in pixels " << DEC(inNumPixels) << " too small (< 12)"); return false;} // Invalid width
1797  if (inNumPixels % 4) // 6)?
1798  {LOGMYERROR("width in pixels " << DEC(inNumPixels) << " not multiple of 4"); return false;} // Width not evenly divisible by 4
1799 
1800  // Since Y and C may have separate/independent ANC data going on, we're going to split the task and do all
1801  // the even (C) samples first, the come back and repeat it for all of the odd (Y) samples...
1802  for (ULWord comp = 0; comp < 2; comp++)
1803  {
1804  bool bNoMoreAnc (false); // Assume all ANC packets (if any) begin at the first pixel and are contiguous
1805  // (i.e. no gaps between Anc packets). Once a "gap" is seen, this flag is set,
1806  // and the rest of the line turns into a copy.
1807 
1808  ULWord ancCount (0); // Number of bytes to shift and copy (once an ANC packet is found).
1809  // 0 == at the start of a potential new Anc packet.
1810 
1811  ULWord pixNum (0); // The current pixel being inspected (note: NOT the component or sample number!)
1812  UWord checksum (0); // Accumulator for checksum calculations
1813 
1814  while (pixNum < inNumPixels)
1815  {
1816  if (bNoMoreAnc)
1817  { // NoMoreAnc -- there's a gap in the Anc data -- which is assumed to mean there are no more packets on this line.
1818  // Just do a simple 8-bit -> 10-bit expansion with the remaining data on the line...
1819  const ULWord index (2 * pixNum + comp);
1820  const UWord dataValue (UWord(UWord(pInYUV8Buffer[index]) << 2)); // Pad 2 LSBs with zeros
1821 
1822  NTV2_ASSERT (index <= ULWord(outU16YUVLine.size()));
1823  if (index < ULWord(outU16YUVLine.size()))
1824  outU16YUVLine[index] = dataValue;
1825  else
1826  outU16YUVLine.push_back(dataValue);
1827  pixNum++;
1828  }
1829  else
1830  { // Still processing (possible) Anc data...
1831  if (ancCount == 0)
1832  { // AncCount == 0 means we're at the beginning of an Anc packet -- or not...
1833  if ((pixNum + 7) < inNumPixels)
1834  { // An Anc packet has to be at least 7 pixels long to be real...
1835  if ( pInYUV8Buffer [2*(pixNum+0) + comp] == 0x00
1836  && pInYUV8Buffer [2*(pixNum+1) + comp] == 0xFF
1837  && pInYUV8Buffer [2*(pixNum+2) + comp] == 0xFF)
1838  { // "00-FF-FF" means a new Anc packet is being started...
1839  // Stuff "000-3FF-3FF" into the output buffer...
1840  outU16YUVLine [2*pixNum++ + comp] = 0x000;
1841  outU16YUVLine [2*pixNum++ + comp] = 0x3ff;
1842  outU16YUVLine [2*pixNum++ + comp] = 0x3ff;
1843 
1844  ancCount = pInYUV8Buffer[2*(pixNum+2) + comp] + 3 + 1; // Number of data words + DID + SID + DC + checksum
1845  checksum = 0; // Reset checksum accumulator
1846  }
1847  else
1848  bNoMoreAnc = true; // No anc here -- assume there's no more for the rest of the line
1849  }
1850  else
1851  bNoMoreAnc = true; // Not enough room for another anc packet here -- assume no more for the rest of the line
1852  } // if ancCount == 0
1853  else if (ancCount == 1)
1854  { // This is the last byte of an anc packet -- the checksum. Since the original conversion to 8 bits
1855  // wiped out part of the original checksum, we've been recalculating it all along until now...
1856  outU16YUVLine [2*pixNum + comp] = checksum & 0x1ff; // LS 9 bits of checksum
1857  outU16YUVLine [2*pixNum + comp] |= (~checksum & 0x100) << 1; // bit 9 = ~bit 8;
1858 
1859  pixNum++;
1860  ancCount--;
1861  } // else if end of valid Anc packet
1862  else
1863  { // ancCount > 0 means an Anc packet is being processed.
1864  // Copy 8-bit data into LS 8 bits, add even parity to bit 8, and ~bit 8 to bit 9...
1865  const UByte ancByte (pInYUV8Buffer [2*pixNum + comp]);
1866  const UWord ancWord (AddEvenParity (ancByte));
1867 
1868  outU16YUVLine [2*pixNum + comp] = ancWord;
1869 
1870  checksum += (ancWord & 0x1ff); // Add LS 9 bits to checksum
1871 
1872  pixNum++;
1873  ancCount--;
1874  } // else copying actual Anc packet
1875  } // else processing an Anc packet
1876  } // for each pixel in the line
1877  } // for each Y/C component (channel)
1878 
1879  return true;
1880 } // Unpack8BitYCbCrToU16sVANCLine
1881 
1882 
1884  UWordSequence & outU16YUVLine,
1885  const uint32_t inNumPixels)
1886 {
1887  const UByte * pInYUV8Buffer (reinterpret_cast<const UByte*>(pInYUV8Line));
1888  const ULWord maxNumElements(inNumPixels * 2);
1889 
1890  outU16YUVLine.clear ();
1891  outU16YUVLine.reserve (maxNumElements);
1892  while (outU16YUVLine.size() < size_t(maxNumElements))
1893  outU16YUVLine.push_back(0);
1894 
1895  if (!pInYUV8Buffer)
1896  {LOGMYERROR("NULL/empty YUV8 buffer"); return false;} // NULL pointer
1897  if (inNumPixels < 12)
1898  {LOGMYERROR("width in pixels " << DEC(inNumPixels) << " too small (< 12)"); return false;} // Invalid width
1899  if (inNumPixels % 4)
1900  {LOGMYERROR("width in pixels " << DEC(inNumPixels) << " not multiple of 4"); return false;} // Width not evenly divisible by 4
1901 
1902  // In SD, anc data appears in both Y & C...
1903  bool bNoMoreAnc(false); // Assume all ANC packets (if any) begin at the first pixel
1904  // and are contiguous (i.e. no gaps between packets). Once a
1905  // "gap" is seen, this flag is set, and the rest of the line
1906  // is simply copied.
1907  ULWord ancCount(0); // Number of bytes to shift and copy (once an ANC packet is
1908  // found). Zero at the start of a potential new Anc packet.
1909  ULWord ndx(0); // The current pixel being inspected
1910  UWord checksum(0); // Accumulator for checksum calculations
1911 
1912  while (ndx < maxNumElements)
1913  {
1914  if (bNoMoreAnc)
1915  { // NoMoreAnc -- there's a gap in the Anc data -- which is assumed to mean there are
1916  // no more packets on this line. Just do a simple 8-bit -> 10-bit expansion with the
1917  // remaining data on the line...
1918  const UWord dataValue (UWord(UWord(pInYUV8Buffer[ndx]) << 2)); // Pad 2 LSBs with zeros
1919  NTV2_ASSERT (ndx <= ULWord(outU16YUVLine.size()));
1920  if (ndx < ULWord(outU16YUVLine.size()))
1921  outU16YUVLine[ndx] = dataValue;
1922  else
1923  outU16YUVLine.push_back(dataValue);
1924  ndx++;
1925  }
1926  else
1927  { // Still processing (possible) Anc data...
1928  if (ancCount == 0)
1929  { // AncCount == 0 means we're at the beginning of an Anc packet -- or not...
1930  if ((ndx + 7) < maxNumElements)
1931  { // An Anc packet has to be at least 7 pixels long to be real...
1932  if ( pInYUV8Buffer [ndx+0] == 0x00
1933  && pInYUV8Buffer [ndx+1] == 0xFF
1934  && pInYUV8Buffer [ndx+2] == 0xFF)
1935  { // "00-FF-FF" means a new Anc packet is being started...
1936  // Stuff "000-3FF-3FF" into the output buffer...
1937  outU16YUVLine [ndx++] = 0x000;
1938  outU16YUVLine [ndx++] = 0x3ff;
1939  outU16YUVLine [ndx++] = 0x3ff;
1940  ancCount = pInYUV8Buffer[ndx+2] + 3 + 1; // Number of data words + DID + SID + DC + checksum
1941  checksum = 0; // Reset checksum accumulator
1942  }
1943  else
1944  bNoMoreAnc = true; // No anc here -- assume there's no more for the rest of the line
1945  }
1946  else
1947  bNoMoreAnc = true; // Not enough room for another anc packet here -- assume no more for the rest of the line
1948  } // if ancCount == 0
1949  else if (ancCount == 1)
1950  { // This is the last byte of an anc packet -- the checksum. Since the original conversion to 8 bits
1951  // wiped out part of the original checksum, we've been recalculating it all along until now...
1952  outU16YUVLine[ndx] = checksum & 0x1ff; // LS 9 bits of checksum
1953  outU16YUVLine[ndx] |= (~checksum & 0x100) << 1; // bit 9 = ~bit 8;
1954  ndx++;
1955  ancCount--;
1956  } // else if end of valid Anc packet
1957  else
1958  { // ancCount > 0 means an Anc packet is being processed.
1959  // Copy 8-bit data into LS 8 bits, add even parity to bit 8, and ~bit 8 to bit 9...
1960  const UByte ancByte (pInYUV8Buffer[ndx]);
1961  const UWord ancWord (AddEvenParity(ancByte));
1962  outU16YUVLine[ndx] = ancWord;
1963  checksum += (ancWord & 0x1ff); // Add LS 9 bits to checksum
1964  ndx++;
1965  ancCount--;
1966  } // else copying actual Anc packet
1967  } // else processing an Anc packet
1968  } // for each byte in the line
1969  return true;
1970 } // Unpack8BitYCbCrToU16sVANCLineSD
1971 
1972 
1973 void AJAAncillaryData::GetInstanceCounts (uint32_t & outConstructed, uint32_t & outDestructed)
1974 {
1975 #if defined(_DEBUG)
1976  outConstructed = gConstructCount;
1977  outDestructed = gDestructCount;
1978 #else
1979  outConstructed = outDestructed = 0;
1980 #endif
1981 }
1982 
1984 {
1985 #if defined(_DEBUG)
1987 #endif
1988 }
1989 
1991 {
1992 #if defined(_DEBUG)
1994 #else
1995  return 0;
1996 #endif
1997 }
1998 
2000 {
2001 #if defined(_DEBUG)
2002  return gConstructCount;
2003 #else
2004  return 0;
2005 #endif
2006 }
2007 
2009 {
2010 #if defined(_DEBUG)
2011  return gDestructCount;
2012 #else
2013  return 0;
2014 #endif
2015 }
2016 
2017 typedef map<uint8_t, string> DIDToStringMap;
2018 typedef DIDToStringMap::const_iterator DIDToStringMapCI;
2019 typedef pair<uint8_t, string> DIDToStringPair;
2020 typedef map<AJAAncDIDSIDPair, string> DIDSIDToStringMap;
2021 typedef DIDSIDToStringMap::const_iterator DIDSIDToStringMapCI;
2022 typedef pair<AJAAncDIDSIDPair, string> DIDSIDToStringPair;
2026 
2027 string AJAAncillaryData::DIDSIDToString (const uint8_t inDID, const uint8_t inSID)
2028 {
2030  if (sDIDSIDToStringMap.empty())
2031  {
2032  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x08,0x08), "SMPTE-291 Control Packet"));
2033  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x40,0x01), "RP-305 SDTI Header Data"));
2034  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x40,0x02), "RP-348 HD-SDTI Header Data"));
2035  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x40,0x04), "SMPTE-427 Link Encryp Key Msg 1"));
2036  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x40,0x05), "SMPTE-427 Link Encryp Key Msg 2"));
2037  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x40,0x06), "SMPTE-427 Link Encryp MetaD"));
2038  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x41,0x01), "SMPTE-352M Payload ID"));
2039  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x41,0x05), "SMPTE-2016-3 ADF/Bar Data"));
2040  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x41,0x06), "SMPTE-2016-4 Pan & Scan Data"));
2041  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x41,0x07), "SMPTE-2010 ANSI/SCTE 104 Msgs"));
2042  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x41,0x08), "SMPTE-2031 DVB/SCTE VBI Data"));
2043  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x43,0x01), "BT.1685 Inter-Station Ctrl Data"));
2044  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x43,0x02), "RDD08/OP-47 Teletext Subtitling"));
2045  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x43,0x03), "RDD08/OP-47 VANC Multipacket"));
2046  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x43,0x04), "ARIB TR-B29 AV Sig Error Mon MetaD"));
2047  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x43,0x05), "RDD18 Camera Params"));
2048  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x44,0x04), "RP-214 KLV-Encoded MetaData"));
2049  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x44,0x14), "RP-214 KLV-Encoded MetaData"));
2050  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x44,0x44), "RP-223 UMID & Prog ID Label Data"));
2051  for (uint8_t sid(1); sid < 0x0A; sid++)
2052  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x45,sid), "RP-2020 Compr/Dolby Aud MetaD"));
2053  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x50,0x01), "RDD08 WSS Data"));
2054  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x50,0x51), "CineLink-2 Link Encryp MetaD"));
2055  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x51,0x01), "RP-215 Film Transfer Info"));
2056  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x51,0x02), "RDD-18 Cam Param MetaD Set Acq"));
2057  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x5F,0xDF), "ARIB STD-B37 HD Captions"));
2058  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x5F,0xDE), "ARIB STD-B37 SD Captions"));
2059  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x5F,0xDD), "ARIB STD-B37 Analog Captions"));
2060  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x5F,0xDC), "ARIB STD-B37 Mobile Captions"));
2061  for (uint8_t sid(0xD0); sid < 0xE0; sid++)
2062  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x5F,sid), "ARIB STD-B37 ??? Captions"));
2063  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x60,0x60), "SMPTE-12M ATC Timecode"));
2064  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x61,0x01), "SMPTE-334 HD CEA-708 CC"));
2065  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x61,0x02), "SMPTE-334 SD CEA-608 CC"));
2066  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x62,0x01), "RP-207 DTV Program Desc"));
2067  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x62,0x02), "SMPTE-334 Data Broadcast"));
2068  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x62,0x03), "RP-208 VBI Data"));
2069  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x64,0x64), "RP-196 LTC in HANC (Obs)"));
2070  sDIDSIDToStringMap.insert(DIDSIDToStringPair(AJAAncDIDSIDPair(0x64,0x7F), "RP-196 VITC in HANC (Obs)"));
2071  }
2072  if (sDIDToStringMap.empty())
2073  {
2074  sDIDToStringMap.insert(DIDToStringPair(0x00, "SMPTE-291 Control Packet"));
2075  sDIDToStringMap.insert(DIDToStringPair(0x08, "SMPTE-291 Ctrl Pkt"));
2076  sDIDToStringMap.insert(DIDToStringPair(0x40, "RP-305 SDTI / RP-348 HD-SDTI / SMPTE-427 Link Encrypt"));
2077  sDIDToStringMap.insert(DIDToStringPair(0x41, "SMPTE-352M / SMPTE-2016 / SMPTE-2010 / SMPTE-2031"));
2078  sDIDToStringMap.insert(DIDToStringPair(0x43, "BT.1685 / RDD08/OP-47 / ARIB TR-B29 / RDD18"));
2079  sDIDToStringMap.insert(DIDToStringPair(0x44, "RP-214 KLV / RP-223 UMID+ProgramID Labels"));
2080  sDIDToStringMap.insert(DIDToStringPair(0x45, "RP-2020 Compressed/Dolby Audio"));
2081  sDIDToStringMap.insert(DIDToStringPair(0x50, "RDD08 WSS Data / CineLink-2 Link Encryption"));
2082  sDIDToStringMap.insert(DIDToStringPair(0x51, "RP-215 Film Xfer Info / RDD-18 Camera Params"));
2083  sDIDToStringMap.insert(DIDToStringPair(0x5F, "ARIB STD-B37 Captions"));
2084  sDIDToStringMap.insert(DIDToStringPair(0x60, "SMPTE-12M ATC Timecode"));
2085  sDIDToStringMap.insert(DIDToStringPair(0x61, "SMPTE-334 Captions"));
2086  sDIDToStringMap.insert(DIDToStringPair(0x62, "RP-207 DTV Prog / SMPTE-334 Data / RP-208 VBI"));
2087  sDIDToStringMap.insert(DIDToStringPair(0x64, "RP-196 LTC/VITC in HANC"));
2088  sDIDToStringMap.insert(DIDToStringPair(0x80, "SMPTE-291 Ctrl Pkt 'Marked for Deletion'"));
2089  sDIDToStringMap.insert(DIDToStringPair(0x84, "SMPTE-291 Ctrl Pkt 'End Marker'"));
2090  sDIDToStringMap.insert(DIDToStringPair(0x88, "SMPTE-291 Ctrl Pkt 'Start Marker'"));
2091  sDIDToStringMap.insert(DIDToStringPair(0xA0, "SMPTE-299M 3G HD Audio Ctrl Grp8 (Ch 29-32)"));
2092  sDIDToStringMap.insert(DIDToStringPair(0xA1, "SMPTE-299M 3G HD Audio Ctrl Grp7 (Ch 25-28)"));
2093  sDIDToStringMap.insert(DIDToStringPair(0xA2, "SMPTE-299M 3G HD Audio Ctrl Grp6 (Ch 21-24)"));
2094  sDIDToStringMap.insert(DIDToStringPair(0xA3, "SMPTE-299M 3G HD Audio Ctrl Grp5 (Ch 17-20)"));
2095  sDIDToStringMap.insert(DIDToStringPair(0xA4, "SMPTE-299M 3G HD Audio Data Grp8 (Ch 29-32)"));
2096  sDIDToStringMap.insert(DIDToStringPair(0xA5, "SMPTE-299M 3G HD Audio Data Grp7 (Ch 25-28)"));
2097  sDIDToStringMap.insert(DIDToStringPair(0xA6, "SMPTE-299M 3G HD Audio Data Grp6 (Ch 21-24)"));
2098  sDIDToStringMap.insert(DIDToStringPair(0xA7, "SMPTE-299M 3G HD Audio Data Grp5 (Ch 17-20)"));
2099  sDIDToStringMap.insert(DIDToStringPair(0xD1, "AJA QA F1 Test Packet"));
2100  sDIDToStringMap.insert(DIDToStringPair(0xD2, "AJA QA F1 Test Packet"));
2101  sDIDToStringMap.insert(DIDToStringPair(0xD3, "AJA QA F2 Test Packet"));
2102  sDIDToStringMap.insert(DIDToStringPair(0xE0, "SMPTE-299M HD Audio Ctrl Grp4 (Ch 13-16)"));
2103  sDIDToStringMap.insert(DIDToStringPair(0xE1, "SMPTE-299M HD Audio Ctrl Grp3 (Ch 9-12)"));
2104  sDIDToStringMap.insert(DIDToStringPair(0xE2, "SMPTE-299M HD Audio Ctrl Grp2 (Ch 5-8)"));
2105  sDIDToStringMap.insert(DIDToStringPair(0xE3, "SMPTE-299M HD Audio Ctrl Grp1 (Ch 1-4)"));
2106  sDIDToStringMap.insert(DIDToStringPair(0xE4, "SMPTE-299M HD Audio Grp4 (Ch 13-16)"));
2107  sDIDToStringMap.insert(DIDToStringPair(0xE5, "SMPTE-299M HD Audio Grp3 (Ch 9-12)"));
2108  sDIDToStringMap.insert(DIDToStringPair(0xE6, "SMPTE-299M HD Audio Grp2 (Ch 5-8)"));
2109  sDIDToStringMap.insert(DIDToStringPair(0xE7, "SMPTE-299M HD Audio Grp1 (Ch 1-4)"));
2110  sDIDToStringMap.insert(DIDToStringPair(0xEC, "SMPTE-272M SD Audio Ctrl Grp4 (Ch 13-16)"));
2111  sDIDToStringMap.insert(DIDToStringPair(0xED, "SMPTE-272M SD Audio Ctrl Grp3 (Ch 9-12)"));
2112  sDIDToStringMap.insert(DIDToStringPair(0xEE, "SMPTE-272M SD Audio Ctrl Grp2 (Ch 5-8"));
2113  sDIDToStringMap.insert(DIDToStringPair(0xEF, "SMPTE-272M SD Audio Ctrl Grp1 (Ch 1-4)"));
2114  sDIDToStringMap.insert(DIDToStringPair(0xF0, "SMPTE-315 Camera Position"));
2115  sDIDToStringMap.insert(DIDToStringPair(0xF4, "RP-165 Error Detect/Checkwords"));
2116  sDIDToStringMap.insert(DIDToStringPair(0xF8, "SMPTE-272M SD Audio Ext Data Grp4 (Ch 13-16)"));
2117  sDIDToStringMap.insert(DIDToStringPair(0xF9, "SMPTE-272M SD Audio Data Grp4 (Ch 13-16)"));
2118  sDIDToStringMap.insert(DIDToStringPair(0xFA, "SMPTE-272M SD Audio Ext Data Grp3 (Ch 9-12)"));
2119  sDIDToStringMap.insert(DIDToStringPair(0xFB, "SMPTE-272M SD Audio Data Grp3 (Ch 9-12)"));
2120  sDIDToStringMap.insert(DIDToStringPair(0xFC, "SMPTE-272M SD Audio Ext Data Grp2 (Ch 5-8"));
2121  sDIDToStringMap.insert(DIDToStringPair(0xFD, "SMPTE-272M SD Audio Data Grp2 (Ch 5-8"));
2122  sDIDToStringMap.insert(DIDToStringPair(0xFE, "SMPTE-272M SD Audio Ext Data Grp1 (Ch 1-4)"));
2123  sDIDToStringMap.insert(DIDToStringPair(0xFF, "SMPTE-272M SD Audio Data Grp1 (Ch 1-4)"));
2124  }
2125  const AJAAncDIDSIDPair didsid(inDID, inSID);
2126  DIDSIDToStringMapCI it(sDIDSIDToStringMap.find(didsid));
2127  if (it != sDIDSIDToStringMap.end())
2128  return it->second;
2129  DIDToStringMapCI didIt(sDIDToStringMap.find(inDID));
2130  if (didIt != sDIDToStringMap.end())
2131  return didIt->second;
2132  return "";
2133 } // DIDSIDToString
2134 
2135 static const NTV2DIDSet sValidHDMIAuxPacketTypes = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
2136  0x80, 0x81, 0x82, 0x83, 0x84, 0x85}; // <== InfoFrame types
2137 
2138 string AJAAncillaryData::AuxPacketTypeToString (const uint8_t auxPacketType)
2139 {
2140  switch (auxPacketType)
2141  {
2142  case 0x01: return "Audio Clock Regeneration (N/CTS)";
2143  case 0x02: return "Audio Sample (L-PCM & IEC-61937 compressed)";
2144  case 0x03: return "General Control";
2145  case 0x04: return "ACP Packet";
2146  case 0x05: return "ISRC1 Packet";
2147  case 0x06: return "ISRC2 Packet";
2148  case 0x07: return "One Bit Audio Sample Packet";
2149  case 0x08: return "DST Audio Packet";
2150  case 0x09: return "High Bitrate Audio Stream Packet (IEC-61937)";
2151  case 0x0A: return "Gamut Metadata Packet";
2152  case 0x80: return "General InfoFrame Packet"; // May not be valid
2153  case 0x81: return "Vendor-Specific InfoFrame";
2154  case 0x82: return "AVI InfoFrame";
2155  case 0x83: return "Source Product Descriptor InfoFrame";
2156  case 0x84: return "Audio InfoFrame";
2157  case 0x85: return "MPEG Source InfoFrame";
2158  }
2159  return "";
2160 } // AuxPacketTypeToString
2161 
2162 bool AJAAncillaryData::AuxPacketTypeIsValid (const uint8_t inAuxPktType)
2163 {
2164  return sValidHDMIAuxPacketTypes.find(inAuxPktType) != sValidHDMIAuxPacketTypes.end();
2165 }
2166 
2168 // AJARTPAncPayloadHeader
2169 
2170 
2172 {
2173  if (inBuffer.IsNULL())
2174  return false;
2175  // Peek in buffer and see if it starts with an RTP header...
2177  if (!hdr.ReadFromBuffer(inBuffer))
2178  return false;
2179  return hdr.IsValid();
2180 }
2181 
2183  : mVBits (2), // Playout: don't care -- hardware sets this
2184  mPBit (false), // Playout: don't care -- hardware sets this
2185  mXBit (false), // Playout: don't care -- hardware sets this
2186  mMarkerBit (false), // Playout: don't care -- hardware sets this
2187  mCCBits (0), // Playout: don't care -- hardware sets this
2188  mPayloadType (0), // Playout: don't care -- hardware sets this
2189  mSequenceNumber (0), // Playout: don't care -- hardware sets this
2190  mTimeStamp (0), // Playout: don't care -- hardware sets this
2191  mSyncSourceID (0), // Playout: client sets this
2192  mPayloadLength (0), // Playout: WriteIPAncData sets this
2193  mAncCount (0), // Playout: WriteIPAncData sets this
2194  mFieldSignal (0) // Playout: WriteIPAncData sets this
2195 {
2196 }
2197 
2198 bool AJARTPAncPayloadHeader::GetPacketHeaderULWordForIndex (const unsigned inIndex0, uint32_t & outULWord) const
2199 {
2200  switch (inIndex0)
2201  {
2202  case 0:
2203  {
2204  uint32_t u32(uint32_t(mVBits << 30));
2205  u32 |= uint32_t(mPBit ? 1 : 0) << 29;
2206  u32 |= uint32_t(mPBit ? 1 : 0) << 29;
2207  u32 |= uint32_t(mXBit ? 1 : 0) << 28;
2208  u32 |= uint32_t(mCCBits & 0x0000000F) << 24;
2209  u32 |= uint32_t(IsEndOfFieldOrFrame() ? 1 : 0) << 23;
2210  u32 |= uint32_t(GetPayloadType() & 0x0000007F) << 16;
2211  u32 |= uint32_t(GetSequenceNumber() & 0x0000FFFF);
2212  outULWord = ENDIAN_32HtoN(u32);
2213  break;
2214  }
2215 
2216  case 1:
2217  outULWord = ENDIAN_32HtoN(GetTimeStamp());
2218  break;
2219 
2220  case 2:
2221  outULWord = ENDIAN_32HtoN(GetSyncSourceID());
2222  break;
2223 
2224  case 3:
2225  {
2226  const uint32_t u32 ((GetSequenceNumber() & 0xFFFF0000) | (GetPayloadLength()));
2227  outULWord = ENDIAN_32HtoN(u32);
2228  break;
2229  }
2230 
2231  case 4:
2232  {
2233  uint32_t u32(uint32_t(GetAncPacketCount() & 0x000000FF) << 24);
2234  u32 |= uint32_t(GetFieldSignal() & 0x00000003) << 22;
2235  outULWord = ENDIAN_32HtoN(u32);
2236  break;
2237  }
2238 
2239  default:
2240  outULWord = 0;
2241  return false;
2242  }
2243  return true;
2244 }
2245 
2246 bool AJARTPAncPayloadHeader::SetFromPacketHeaderULWordAtIndex(const unsigned inIndex0, const uint32_t inULWord)
2247 {
2248  const uint32_t u32 (ENDIAN_32NtoH(inULWord));
2249  switch (inIndex0)
2250  {
2251  case 0: mVBits = uint8_t(u32 >> 30);
2252  mPBit = (u32 & 0x20000000) ? true : false;
2253  mXBit = (u32 & 0x10000000) ? true : false;
2254  mCCBits = uint8_t((u32 & 0x0F000000) >> 24);
2255  mMarkerBit = (u32 & 0x00800000) ? true : false;
2256  mPayloadType = uint8_t((u32 & 0x007F0000) >> 16);
2257  mSequenceNumber = (mSequenceNumber & 0xFFFF0000) | (u32 & 0x0000FFFF); // Replace LS 16 bits
2258  break;
2259 
2260  case 1: mTimeStamp = u32;
2261  break;
2262 
2263  case 2: mSyncSourceID = u32;
2264  break;
2265 
2266  case 3: mSequenceNumber = (u32 & 0xFFFF0000) | (mSequenceNumber & 0x0000FFFF); // Replace MS 16 bits
2267  mPayloadLength = uint16_t(u32 & 0x0000FFFF);
2268  break;
2269 
2270  case 4: mAncCount = uint8_t((u32 & 0xFF000000) >> 24);
2271  mFieldSignal = uint8_t((u32 & 0x00C00000) >> 22);
2272  break;
2273 
2274  default: return false;
2275  }
2276  return true;
2277 }
2278 
2279 bool AJARTPAncPayloadHeader::WriteToULWordVector (ULWordSequence & outVector, const bool inReset) const
2280 {
2281  if (inReset)
2282  outVector.clear();
2283  while (outVector.size() < 5)
2284  outVector.push_back(0);
2285  for (unsigned ndx(0); ndx < 5; ndx++)
2286  outVector[ndx] = GetPacketHeaderULWordForIndex(ndx);
2287  return true;
2288 }
2289 
2290 bool AJARTPAncPayloadHeader::WriteToBuffer (NTV2Buffer & outBuffer, const ULWord inU32Offset) const
2291 {
2292  const ULWord startingByteOffset (inU32Offset * sizeof(uint32_t));
2293  if ((startingByteOffset + ULWord(GetHeaderByteCount())) > outBuffer.GetByteCount())
2294  return false; // Buffer too small
2295  uint32_t * pU32s (reinterpret_cast<uint32_t*>(outBuffer.GetHostAddress(startingByteOffset)));
2296  for (unsigned ndx(0); ndx < 5; ndx++)
2297  pU32s[ndx] = GetPacketHeaderULWordForIndex(ndx);
2298  return true;
2299 }
2300 
2302 {
2303  // Note: uint32_t's are assumed to be in network byte order
2304  if (inVector.size() < 5)
2305  return false; // Too small
2306  for (unsigned ndx(0); ndx < 5; ndx++)
2307  if (!SetFromPacketHeaderULWordAtIndex(ndx, inVector[ndx]))
2308  return false;
2309  return true;
2310 }
2311 
2313 {
2314  if (inBuffer.GetByteCount() < GetHeaderByteCount())
2315  return false; // Too small
2316  const uint32_t * pU32s (reinterpret_cast <const uint32_t *> (inBuffer.GetHostPointer()));
2317  for (unsigned ndx(0); ndx < 5; ndx++)
2318  if (!SetFromPacketHeaderULWordAtIndex(ndx, pU32s[ndx]))
2319  return false;
2320  return true;
2321 }
2322 
2323 const string & AJARTPAncPayloadHeader::FieldSignalToString (const uint8_t inFBits)
2324 {
2325  static const string sStrs[] = { "p/noF", "BAD", "i/F1", "i/F2" };
2326  return sStrs[inFBits & 0x03];
2327 }
2328 
2330 {
2331  return mVBits == inRHS.mVBits
2332  && mPBit == inRHS.mPBit
2333  && mXBit == inRHS.mXBit
2334  && mCCBits == inRHS.mCCBits
2335  && mMarkerBit == inRHS.mMarkerBit
2336  && mPayloadType == inRHS.mPayloadType
2337  && mSequenceNumber == inRHS.mSequenceNumber
2338  && mTimeStamp == inRHS.mTimeStamp
2339  && mSyncSourceID == inRHS.mSyncSourceID
2340  && mPayloadLength == inRHS.mPayloadLength
2341  && mAncCount == inRHS.mAncCount
2342  && mFieldSignal == inRHS.mFieldSignal;
2343 }
2344 
2345 ostream & AJARTPAncPayloadHeader::Print (ostream & inOutStream) const
2346 { // Translate back to host byte order before printing:
2347  const uint32_t word0 (ENDIAN_32NtoH(GetPacketHeaderULWordForIndex(0)));
2348  inOutStream << xHEX0N(word0,8)
2349 // << "|" << bBIN032(word0)
2350  << ": V=" << DEC(uint16_t(mVBits))
2351  << " P=" << mPBit << " X=" << mXBit << " CC=" << DEC(uint16_t(mCCBits))
2352  << " M=" << (IsEndOfFieldOrFrame()?"EOF":"0") << " PT=" << xHEX0N(uint16_t(GetPayloadType()),2)
2353  << " Seq#=" << xHEX0N(GetSequenceNumber(),8) << " TS=" << xHEX0N(GetTimeStamp(),8)
2354  << " SSRC=" << xHEX0N(GetSyncSourceID(),8) << " PayLen=" << DEC(GetPayloadLength())
2355  << " AncCnt=" << DEC(uint16_t(GetAncPacketCount())) << " F=" << FieldSignalToString(GetFieldSignal())
2356  << (IsValid() ? "" : " (invalid)");
2357  return inOutStream;
2358 }
2359 
2361 { // Return TRUE if all of my fields are zero...
2362  return !(mVBits || mPBit || mXBit || mCCBits || mMarkerBit || mPayloadType || mSequenceNumber || mTimeStamp || mSyncSourceID || mPayloadLength || mAncCount || mFieldSignal);
2363 }
2364 
2366 { // Simple validation -- Check that...
2367  return mVBits == 0x02 // Version == 2
2368  && !IsNULL() // Not NULL
2369  && IsValidFieldSignal(); // Valid field bits
2370 }
2371 
2372 
2374 // AJARTPAncPacketHeader
2375 
2377  : mCBit (false),
2378  mSBit (false),
2379  mLineNum (0),
2380  mHOffset (0),
2381  mStreamNum (0)
2382 {
2383 }
2384 
2386  : mCBit (false),
2387  mSBit (false),
2388  mLineNum (0),
2389  mHOffset (0),
2390  mStreamNum (0)
2391 {
2392  SetFrom(inLoc);
2393 }
2394 
2396 {
2397  // In network byte order:
2398  //
2399  // 0 1 2 3
2400  // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2401  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2402  // |C| Line_Number | Horizontal_Offset |S| StreamNum |
2403  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2404  uint32_t u32(0); // Build little-endian 32-bit ULWord with this
2405  u32 |= (uint32_t(GetLineNumber()) & 0x000007FF) << 20; // 11-bit line number
2406  u32 |= (IsCBitSet() ? 0x80000000 : 0x00000000);
2407  u32 |= (uint32_t(GetHorizOffset()) & 0x00000FFF) << 8; // 12-bit horiz offset
2408  u32 |= IsSBitSet() ? 0x00000080 : 0x00000000; // Data Stream flag
2409  if (IsSBitSet())
2410  u32 |= uint32_t(GetStreamNumber() & 0x7F); // 7-bit StreamNum
2411  return ENDIAN_32HtoN(u32); // Convert to big-endian
2412 }
2413 
2414 bool AJARTPAncPacketHeader::SetFromULWord (const uint32_t inULWord)
2415 {
2416  const uint32_t u32 (ENDIAN_32NtoH(inULWord));
2417  // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2418  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2419  // |C| Line_Number | Horizontal_Offset |S| StreamNum |
2420  // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2421  if (u32 & 0x80000000)
2422  SetCChannel();
2423  else
2424  SetYChannel();
2425  SetLineNumber(uint16_t((u32 & 0x7FF00000) >> 20));
2426  SetHorizOffset(uint16_t((u32 & 0x000FFF00) >> 8));
2427  SetStreamNumber(uint8_t(u32 & 0x0000007F));
2428  SetDataStreamFlag(u32 & 0x00000080);
2429  return true;
2430 }
2431 
2432 bool AJARTPAncPacketHeader::WriteToULWordVector (ULWordSequence & outVector, const bool inReset) const
2433 {
2434  if (inReset)
2435  outVector.clear();
2436  outVector.push_back(GetULWord());
2437  return true;
2438 }
2439 
2440 bool AJARTPAncPacketHeader::ReadFromULWordVector (const ULWordSequence & inVector, const unsigned inIndex0)
2441 {
2442  if (inIndex0 >= inVector.size())
2443  return false; // Bad index -- out of range
2444  return SetFromULWord(inVector[inIndex0]);
2445 }
2446 
2448 {
2449  AJAAncDataLoc result;
2450  result.SetLineNumber(GetLineNumber()).SetHorizontalOffset(GetHorizOffset())
2453  if (IsSBitSet())
2454  {
2455  // e.g. SMPTE ST 425-3 DL 3Gbps, data streams are numbered 1-4, so DS1/DS2 on linkA, DS3/DS4 on linkB
2456  result.SetDataStream(AJAAncDataStream(GetStreamNumber()));
2457  if (IS_LINKB_AJAAncDataStream(result.GetDataStream()))
2458  result.SetDataLink(AJAAncDataLink_B);
2459  }
2460  return result;
2461 }
2462 
2464 {
2465  const AJAAncDataLink lnk (inLoc.GetDataLink());
2466  const AJAAncDataStream ds (inLoc.GetDataStream());
2467  const AJAAncDataChannel dChan (inLoc.GetDataChannel());
2468 
2469  // @bug Dang, the sense of the C bit is opposite of our AJAAncDataChannel enum!
2470  // The C bit should be '1' for AJAAncDataChannel_C (0).
2471  // The C bit should be '0' for AJAAncDataChannel_Y (1).
2472  // The C bit should be '0' for SD, but we use AJAAncDataChannel_Both (0) for this,
2473  // which is indistinguishable from AJAAncDataChannel_C (0).
2474  // @todo This needs to be addressed.
2475  mCBit = IS_VALID_AJAAncDataChannel(dChan) && (dChan != AJAAncDataChannel_Y);
2476 
2477  // Data Stream Flag
2478  // '0': No guidance -- don't know -- don't care
2479  // '1': StreamNum field carries info about source data stream number
2481 
2482  if (IS_VALID_AJAAncDataLink(lnk))
2483  mStreamNum = uint8_t(lnk);
2484  else if (IS_VALID_AJAAncDataStream(ds))
2485  mStreamNum = uint8_t(ds);
2486  else
2487  mStreamNum = 0;
2488 
2489  mLineNum = inLoc.GetLineNumber();
2490  mHOffset = inLoc.GetHorizontalOffset();
2491 
2492  return *this;
2493 }
2494 
2495 ostream & AJARTPAncPacketHeader::Print (ostream & inOutStream) const
2496 {
2497  inOutStream << xHEX0N(GetULWord(),8) << ": C=" << (IsCBitSet() ? "1" : "0")
2498  << " Line=" << DEC(GetLineNumber()) << " HOff=" << DEC(GetHorizOffset())
2499  << " S=" << (IsSBitSet() ? "1" : "0") << " Strm=" << DEC(uint16_t(GetStreamNumber()));
2500  return inOutStream;
2501 }
sDIDSIDToStringMap
static DIDSIDToStringMap sDIDSIDToStringMap
Definition: ancillarydata.cpp:2025
AJAAncillaryData::SetLocationHorizOffset
virtual AJAStatus SetLocationHorizOffset(const uint16_t inOffset)
Sets my ancillary data "location" horizontal offset.
Definition: ancillarydata.cpp:331
AJAAncillaryData::m_frameID
uint32_t m_frameID
ID of my originating frame, if known.
Definition: ancillarydata.h:1161
IS_VALID_AJAAncBufferFormat
#define IS_VALID_AJAAncBufferFormat(_x_)
Definition: ancillarydata.h:508
AJAAncillaryData::AJAAncillaryData
AJAAncillaryData()
My default constructor.
Definition: ancillarydata.cpp:92
DIDToStringPair
pair< uint8_t, string > DIDToStringPair
Definition: ancillarydata.cpp:2019
AJAAncillaryData::GetGUMPHeaderByte2
virtual uint8_t GetGUMPHeaderByte2(void) const
Definition: ancillarydata.cpp:862
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:725
AJARTPAncPayloadHeader::AJARTPAncPayloadHeader
AJARTPAncPayloadHeader()
My default constructor.
Definition: ancillarydata.cpp:2182
AJAAncDataLineNumber_AnyVanc
#define AJAAncDataLineNumber_AnyVanc
Packet placed/found on any line past RP168 switch line and before SAV.
Definition: ancillarydata.h:199
sValidHDMIAuxPacketTypes
static const NTV2DIDSet sValidHDMIAuxPacketTypes
Definition: ancillarydata.cpp:2135
AJAAncDataLoc
Defines where the ancillary data can be found within a video stream.
Definition: ancillarydata.h:225
AJAAncillaryData::m_userData
uint64_t m_userData
User data (for client use)
Definition: ancillarydata.h:1162
AJAAncDataSpaceToString
const string & AJAAncDataSpaceToString(const AJAAncDataSpace inValue, const bool inCompact)
Definition: ancillarydata.cpp:1261
AJAAncDataLineNumber_Unknown
#define AJAAncDataLineNumber_Unknown
Packet line number is unknown.
Definition: ancillarydata.h:196
DIDSIDToStringPair
pair< AJAAncDIDSIDPair, string > DIDSIDToStringPair
Definition: ancillarydata.cpp:2022
ancillarydata.h
Declares the AJAAncillaryData class.
AJAAncillaryData::SetSID
virtual AJAStatus SetSID(const uint8_t inSID)
Sets my Secondary Data ID (SID) - (aka the Data Block Number (DBN) for "Type 1" SMPTE-291 packets).
Definition: ancillarydata.cpp:207
AJAAncillaryData::ByteVector
std::vector< uint8_t > ByteVector
Definition: ancillarydata.h:1137
LOGMYWARN
#define LOGMYWARN(__x__)
Definition: ancillarydata.cpp:26
AJAAncillaryData::m_DID
uint8_t m_DID
Official SMPTE ancillary packet ID (w/o parity)
Definition: ancillarydata.h:1152
AJARTPAncPacketHeader::SetYChannel
virtual AJARTPAncPacketHeader & SetYChannel(void)
Sets my "C" channel bit setting to 'false'.
Definition: ancillarydata.h:1480
IS_VALID_AJAAncDataSpace
#define IS_VALID_AJAAncDataSpace(_x_)
Definition: ancillarydata.h:183
AJAAncillaryData::Calculate9BitChecksum
virtual uint16_t Calculate9BitChecksum(void) const
Generates the official SMPTE 291 9-bit checksum from the DID + SID + DC + payload data.
Definition: ancillarydata.cpp:249
AJAAncDataType_Unknown
@ AJAAncDataType_Unknown
Includes data that is valid, but we don't recognize.
Definition: ancillarydata.h:46
AJA_ENDIAN_32HtoN
#define AJA_ENDIAN_32HtoN(__val__)
Definition: ancillarydata.cpp:71
AJARTPAncPacketHeader::SetCChannel
virtual AJARTPAncPacketHeader & SetCChannel(void)
Sets my "C" channel bit setting to 'true'.
Definition: ancillarydata.h:1474
AJAAncDataChannelToString
const string & AJAAncDataChannelToString(const AJAAncDataChannel inValue, const bool inCompact)
Definition: ancillarydata.cpp:1252
DIDSIDToStringMapCI
DIDSIDToStringMap::const_iterator DIDSIDToStringMapCI
Definition: ancillarydata.cpp:2021
NULL
#define NULL
Definition: ntv2caption608types.h:19
gConstructCount
static uint32_t gConstructCount(0)
AJARTPAncPacketHeader::AJARTPAncPacketHeader
AJARTPAncPacketHeader()
My default constructor.
Definition: ancillarydata.cpp:2376
IS_VALID_AJAAncDataLink
#define IS_VALID_AJAAncDataLink(_x_)
Definition: ancillarydata.h:89
NTV2Buffer
Describes a user-space buffer on the host computer. I have an address and a length,...
Definition: ntv2publicinterface.h:6141
AJAAncDataLocToString
string AJAAncDataLocToString(const AJAAncDataLoc &inValue, const bool inCompact)
Definition: ancillarydata.cpp:1358
AJA_STATUS_SUCCESS
@ AJA_STATUS_SUCCESS
Definition: types.h:381
AJAAncDataLineNumber_Anywhere
#define AJAAncDataLineNumber_Anywhere
Definition: ancillarydata.h:198
DIDToStringMapCI
DIDToStringMap::const_iterator DIDToStringMapCI
Definition: ancillarydata.cpp:2018
AJAAncillaryData::ByteVectorIndex
ByteVector::size_type ByteVectorIndex
Definition: ancillarydata.h:1138
NTV2Buffer::GetByteCount
ULWord GetByteCount(void) const
Definition: ntv2publicinterface.h:6215
AJAAncDataLineNumber_Future
#define AJAAncDataLineNumber_Future
Line number exceeds 11 bits (future).
Definition: ancillarydata.h:200
NTV2_ASSERT
#define NTV2_ASSERT(_expr_)
Definition: ajatypes.h:508
AJAAncDataChannel
AJAAncDataChannel
Identifies which component of a video stream in which the ancillary data is placed or found.
Definition: ancillarydata.h:129
IS_VALID_AJAAncDataCoding
#define IS_VALID_AJAAncDataCoding(_x_)
Definition: ancillarydata.h:482
AJAAncillaryData::m_location
AJAAncDataLoc m_location
Location of the ancillary data in the video stream (Y or C, HANC or VANC, etc.)
Definition: ancillarydata.h:1155
AJAAncillaryData::GetInstanceCounts
static void GetInstanceCounts(uint32_t &outConstructed, uint32_t &outDestructed)
Definition: ancillarydata.cpp:1973
ENDIAN_32HtoN
static uint32_t ENDIAN_32HtoN(const uint32_t inValue)
Definition: ancillarydata.cpp:78
AJAAncDataLoc::SetLineNumber
AJAAncDataLoc & SetLineNumber(const uint16_t inLineNum)
Sets my anc data line number value.
Definition: ancillarydata.h:393
AncChannelSearch_C
@ AncChannelSearch_C
Only look in chroma samples.
Definition: ancillarydata.h:155
AJAAncillaryData::SetLocationDataStream
virtual AJAStatus SetLocationDataStream(const AJAAncDataStream inStream)
Sets my ancillary data "location" data stream value (DS1,DS2...).
Definition: ancillarydata.cpp:297
AJAAncDataSpace
AJAAncDataSpace
Identified the raster section of a video stream that contains the ancillary data. Deprecated in favor...
Definition: ancillarydata.h:175
AJAAncDataLink_B
@ AJAAncDataLink_B
The ancillary data is associated with Link B of the video stream.
Definition: ancillarydata.h:82
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:1709
AJAAncDataLinkToString
const string & AJAAncDataLinkToString(const AJAAncDataLink inValue, const bool inCompact)
Definition: ancillarydata.cpp:1233
AJAAncillaryData::ByteVectorConstIter
ByteVector::const_iterator ByteVectorConstIter
Definition: ancillarydata.h:1139
AJAAncDataType
AJAAncDataType
Identifies the ancillary data types that are known to this module.
Definition: ancillarydata.h:44
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:623
AJARTPAncPacketHeader
I represent the 4-byte header of an anc packet that's inside an RTP packet.
Definition: ancillarydata.h:1434
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
AJAAncillaryData::m_bufferFmt
AJAAncBufferFormat m_bufferFmt
My originating buffer format, if known.
Definition: ancillarydata.h:1160
IS_VALID_AncChannelSearchSelect
#define IS_VALID_AncChannelSearchSelect(_x_)
Definition: ancillarydata.h:160
gShifts
static const unsigned gShifts[]
Definition: ancillarydata.cpp:924
AJA_STATUS_MEMORY
@ AJA_STATUS_MEMORY
Definition: types.h:397
AJAAncillaryData::SetDID
virtual AJAStatus SetDID(const uint8_t inDataID)
Sets my Data ID (DID).
Definition: ancillarydata.cpp:200
sDIDToStringLock
static AJALock sDIDToStringLock
Definition: ancillarydata.cpp:2023
AncChannelSearchSelectToString
string AncChannelSearchSelectToString(const AncChannelSearchSelect inSelect, const bool inCompact)
Definition: ancillarydata.cpp:1648
AJAAncillaryData::m_auxType
uint8_t m_auxType
HDMI Aux Header Byte 0 (Packet Type)
Definition: ancillarydata.h:1164
AJAAncillaryData::AllocDataMemory
AJAStatus AllocDataMemory(const uint32_t inNumBytes)
Definition: ancillarydata.cpp:171
AJAAncDataLoc::SetDataStream
AJAAncDataLoc & SetDataStream(const AJAAncDataStream inStream)
Sets my data link value to the given value (if valid).
Definition: ancillarydata.h:361
AJAAncillaryData::AuxPacketTypeToString
static std::string AuxPacketTypeToString(const uint8_t inAuxPktType)
Definition: ancillarydata.cpp:2138
IS_KNOWN_AJAAncBufferFormat
#define IS_KNOWN_AJAAncBufferFormat(_x_)
Definition: ancillarydata.h:509
ENDIAN_32NtoH
static uint32_t ENDIAN_32NtoH(const uint32_t inValue)
Definition: ancillarydata.cpp:77
AJAAncDataLoc::Compare
virtual AJAStatus Compare(const AJAAncDataLoc &inRHS) const
Compares me with another location.
Definition: ancillarydata.cpp:1316
RCV2110DBG
#define RCV2110DBG(__x__)
Definition: ancillarydata.cpp:35
AJAAncBufferFormat_HDMI
@ AJAAncBufferFormat_HDMI
HDMI.
Definition: ancillarydata.h:502
AJARTPAncPayloadHeader::FieldSignalToString
static const std::string & FieldSignalToString(const uint8_t inFBits)
Definition: ancillarydata.cpp:2323
AJAAncDataCoding_Raw
@ AJAAncDataCoding_Raw
The ancillary data is in the form of a digitized waveform (e.g. CEA-608 captions, VITC,...
Definition: ancillarydata.h:477
AJARTPAncPacketHeader::SetFrom
virtual AJARTPAncPacketHeader & SetFrom(const AJAAncDataLoc &inLocation)
Resets me from a given AJAAncDataLoc.
Definition: ancillarydata.cpp:2463
AJARTPAncPacketHeader::SetDataStreamFlag
virtual AJARTPAncPacketHeader & SetDataStreamFlag(const bool inFlag)
Sets my data stream flag.
Definition: ancillarydata.h:1510
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:1781
AJAAncDataHorizOffset_Anywhere
#define AJAAncDataHorizOffset_Anywhere
Unspecified – Packet placed/found in any legal area of raster line.
Definition: ancillarydata.h:210
AJAAncillaryData::SetDataLocation
virtual AJAStatus SetDataLocation(const AJAAncDataLoc &inLoc)
Sets my ancillary data "location" within the video stream.
Definition: ancillarydata.cpp:268
AJAAncDataType_Size
@ AJAAncDataType_Size
Definition: ancillarydata.h:61
AJAAncDataLoc::GetHorizontalOffset
uint16_t GetHorizontalOffset(void) const
Definition: ancillarydata.h:339
AJAStatus
AJAStatus
Definition: types.h:378
gMasks
static const uint32_t gMasks[]
Definition: ancillarydata.cpp:925
AJAAncillaryData::~AJAAncillaryData
virtual ~AJAAncillaryData()
My destructor.
Definition: ancillarydata.cpp:122
AJARTPAncPacketHeader::SetLineNumber
virtual AJARTPAncPacketHeader & SetLineNumber(const uint16_t inLineNum)
Sets my line number value to least-significant 11 bits of the given value.
Definition: ancillarydata.h:1487
AJAAncillaryData::Print
virtual std::ostream & Print(std::ostream &inOutStream, const bool inDetailed=false) const
Streams a human-readable representation of me to the given output stream.
Definition: ancillarydata.cpp:1408
AJARTPAncPayloadHeader
I represent the header of a SMPTE 2110 compliant RTP Anc network packet.
Definition: ancillarydata.h:1185
AJARTPAncPayloadHeader::operator==
virtual bool operator==(const AJARTPAncPayloadHeader &inRHS) const
Definition: ancillarydata.cpp:2329
AJAAncDataCodingToString
const string & AJAAncDataCodingToString(const AJAAncDataCoding inValue, const bool inCompact)
Definition: ancillarydata.cpp:1371
AJAAncillaryData::SetLocationVideoLink
virtual AJAStatus SetLocationVideoLink(const AJAAncDataLink inLink)
Sets my ancillary data "location" within the video stream.
Definition: ancillarydata.cpp:285
AJAAncillaryData::m_auxHB2
uint8_t m_auxHB2
HDMI Aux Header Byte 2 (Header Data)
Definition: ancillarydata.h:1166
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:2279
gDestructCount
static uint32_t gDestructCount(0)
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:6237
ULWord
uint32_t ULWord
Definition: ajatypes.h:255
AJARTPAncPacketHeader::ReadFromULWordVector
virtual bool ReadFromULWordVector(const ULWordSequence &inVector, const unsigned inIndex0)
Resets my current state by decoding the 4-byte header value stored in the given ULWordSequence at the...
Definition: ancillarydata.cpp:2440
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:1509
AJAAncDataHorizOffset_AnyVanc
#define AJAAncDataHorizOffset_AnyVanc
VANC – Packet placed/found in any legal area of raster line after SAV, but before EAV.
Definition: ancillarydata.h:212
AJAAncDataSpace_HANC
@ AJAAncDataSpace_HANC
Ancillary data found between EAV and SAV (.
Definition: ancillarydata.h:178
AJAAncillaryData
I am the principal class that stores a single SMPTE-291 SDI ancillary data packet OR the digitized co...
Definition: ancillarydata.h:552
AJAAncillaryData::AppendPayloadData
virtual AJAStatus AppendPayloadData(const uint8_t *pInBuffer, const uint32_t inByteCount)
Appends data from an external buffer onto the end of my existing payload.
Definition: ancillarydata.cpp:404
AJAAncDataLoc::CompareWithInfo
virtual std::string CompareWithInfo(const AJAAncDataLoc &inRHS) const
Compares me with another location and returns a string that describes what's different.
Definition: ancillarydata.cpp:1335
AJAAncDataChannel_Y
@ AJAAncDataChannel_Y
The ancillary data is associated with the luminance (Y) channel of the video stream.
Definition: ancillarydata.h:133
AJAAncillaryData::GetPayloadData
virtual const uint8_t * GetPayloadData(void) const
Definition: ancillarydata.h:801
UWordSequence
std::vector< uint16_t > UWordSequence
An ordered sequence of UWord (uint16_t) values.
Definition: ntv2publicinterface.h:42
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:2312
sENDL
const size_t sENDL(1)
AJAAncillaryData::DIDSIDToString
static std::string DIDSIDToString(const uint8_t inDID, const uint8_t inSDID)
Definition: ancillarydata.cpp:2027
AJARTPAncPacketHeader::WriteToULWordVector
virtual bool WriteToULWordVector(ULWordSequence &outVector, const bool inReset=true) const
Writes my 4-byte header value into the given ULWordSequence. The 4-byte value will be in network byte...
Definition: ancillarydata.cpp:2432
UWord
uint16_t UWord
Definition: ajatypes.h:253
AJAAncDIDSIDPair
std::pair< uint8_t, uint8_t > AJAAncDIDSIDPair
Definition: ancillarydata.h:27
AJAAncHorizOffsetToString
string AJAAncHorizOffsetToString(const uint16_t inValue)
Definition: ancillarydata.cpp:1287
AJAAncillaryData::AppendPayload
virtual AJAStatus AppendPayload(const AJAAncillaryData &inAncData)
Appends payload data from another AJAAncillaryData object to my existing payload.
Definition: ancillarydata.cpp:426
AJAAncillaryData::m_coding
AJAAncDataCoding m_coding
Analog or digital data.
Definition: ancillarydata.h:1156
AJARTPAncPayloadHeader::WriteToBuffer
virtual bool WriteToBuffer(NTV2Buffer &outBuffer, const ULWord inU32Offset=0) const
Writes an RTP packet header based on my current state into the given buffer. Each 32-bit word will be...
Definition: ancillarydata.cpp:2290
AJAAncDataStream
AJAAncDataStream
Identifies which data stream the ancillary data is associated with.
Definition: ancillarydata.h:103
AJA_SUCCESS
#define AJA_SUCCESS(_status_)
Definition: types.h:370
AJAAncillaryData::AsString
virtual std::string AsString(const uint16_t inDumpMaxBytes=0) const
Definition: ancillarydata.cpp:1439
AJAAncBufferFormat_SDI
@ AJAAncBufferFormat_SDI
SDI (AJA "GUMP")
Definition: ancillarydata.h:500
DIDToStringMap
map< uint8_t, string > DIDToStringMap
Definition: ancillarydata.cpp:2017
RCV2110ERR
#define RCV2110ERR(__x__)
Definition: ancillarydata.cpp:31
CheckAncParityAndChecksum
static bool CheckAncParityAndChecksum(const AJAAncillaryData::U16Packet &inYUV16Line, const uint16_t inStartIndex, const uint16_t inTotalCount, const uint16_t inIncrement=2)
Definition: ancillarydata.cpp:1661
AJAAncillaryData::SetPayloadData
virtual AJAStatus SetPayloadData(const uint8_t *pInData, const uint32_t inByteCount)
Copy data from external memory into my local payload memory.
Definition: ancillarydata.cpp:354
IS_VALID_AJAAncDataChannel
#define IS_VALID_AJAAncDataChannel(_x_)
Definition: ancillarydata.h:138
AJALock
Definition: lock.h:28
sDIDToStringMap
static DIDToStringMap sDIDToStringMap
Definition: ancillarydata.cpp:2024
AJAAncillaryData::Unpack8BitYCbCrToU16sVANCLineSD
static bool Unpack8BitYCbCrToU16sVANCLineSD(const void *pInYUV8Line, UWordSequence &outU16YUVLine, const uint32_t inNumPixels)
SD version of Unpack8BitYCbCrToU16sVANCLine.
Definition: ancillarydata.cpp:1883
AJA_STATUS_RANGE
@ AJA_STATUS_RANGE
Definition: types.h:385
AJAAncillaryData::m_rcvDataValid
bool m_rcvDataValid
This is set true (or not) by ParsePayloadData()
Definition: ancillarydata.h:1158
AJA_NULL
#define AJA_NULL
Definition: ajatypes.h:199
IS_VALID_AJAAncDataStream
#define IS_VALID_AJAAncDataStream(_x_)
Definition: ancillarydata.h:113
AJAAncillaryData::SetDataCoding
virtual AJAStatus SetDataCoding(const AJAAncDataCoding inCodingType)
Sets my ancillary data coding type (e.g. digital or analog/raw waveform).
Definition: ancillarydata.cpp:340
AJAAncDataLoc::SetHorizontalOffset
AJAAncDataLoc & SetHorizontalOffset(uint16_t inHOffset)
Specifies the horizontal packet position in the raster.
Definition: ancillarydata.h:408
AJAAncDataHorizOffset_AnyHanc
#define AJAAncDataHorizOffset_AnyHanc
HANC – Packet placed/found in any legal area of raster line after EAV.
Definition: ancillarydata.h:211
AJARTPAncPayloadHeader::IsNULL
virtual bool IsNULL(void) const
Definition: ancillarydata.cpp:2360
AJAAncDataLink
AJAAncDataLink
Identifies which link of a video stream the ancillary data is associated with.
Definition: ancillarydata.h:79
NTV2Buffer::GetHostAddress
void * GetHostAddress(const ULWord inByteOffset, const bool inFromEnd=false) const
Definition: ntv2publicinterface.cpp:1825
NTV2Buffer::GetHostPointer
void * GetHostPointer(void) const
Definition: ntv2publicinterface.h:6198
XMT2110ERR
#define XMT2110ERR(__x__)
Definition: ancillarydata.cpp:37
AJAAutoLock
Definition: lock.h:89
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:2301
AJAAncillaryData::m_SID
uint8_t m_SID
Official SMPTE secondary ID (or DBN - w/o parity)
Definition: ancillarydata.h:1153
AJAAncillaryData::Calculate8BitChecksum
virtual uint8_t Calculate8BitChecksum(void) const
Generates an 8-bit checksum from the DID + SID + DC + payload data.
Definition: ancillarydata.cpp:233
fDEC
#define fDEC(__x__, __w__, __p__)
Definition: ntv2publicinterface.h:5728
AJAAtomic::Increment
static int32_t Increment(int32_t volatile *pTarget)
Definition: atomic.cpp:82
AJAAncillaryData::IDAsString
virtual std::string IDAsString(void) const
Definition: ancillarydata.cpp:1427
AJAAncillaryData::GetNumActiveInstances
static uint32_t GetNumActiveInstances(void)
Definition: ancillarydata.cpp:1990
AJA_STATUS_NULL
@ AJA_STATUS_NULL
Definition: types.h:387
DEC
#define DEC(__x__)
Definition: ntv2publicinterface.h:5694
AJAAncillaryData::SetChecksum
virtual AJAStatus SetChecksum(const uint8_t inChecksum8, const bool inValidate=false)
Sets my 8-bit checksum. Note that it is not usually necessary to generate an 8-bit checksum,...
Definition: ancillarydata.cpp:213
AJARTPAncPayloadHeader::SetFromPacketHeaderULWordAtIndex
virtual bool SetFromPacketHeaderULWordAtIndex(const unsigned inIndex0, const uint32_t inULWord)
Resets (part of) my state from a given 32-bit word in an existing RTP header.
Definition: ancillarydata.cpp:2246
AJARTPAncPacketHeader::AsDataLocation
virtual AJAAncDataLoc AsDataLocation(void) const
Definition: ancillarydata.cpp:2447
AJAAncillaryData::SetLocationLineNumber
virtual AJAStatus SetLocationLineNumber(const uint16_t inLineNum)
Sets my ancillary data "location" frame line number.
Definition: ancillarydata.cpp:321
AJAAncillaryData::GetNumDestructed
static uint32_t GetNumDestructed(void)
Definition: ancillarydata.cpp:2008
AJA_ENDIAN_32NtoH
#define AJA_ENDIAN_32NtoH(__val__)
Definition: ancillarydata.cpp:70
AJAAncDataStream_1
@ AJAAncDataStream_1
The ancillary data is associated with DS1 of the video stream (Link A).
Definition: ancillarydata.h:105
false
#define false
Definition: ntv2devicefeatures.h:25
AJAAncillaryData::m_payload
ByteVector m_payload
My payload data (DC = size)
Definition: ancillarydata.h:1157
AJAAncillaryData::Clear
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values.
Definition: ancillarydata.cpp:159
UByte
uint8_t UByte
Definition: ajatypes.h:250
AJAAncillaryData::GetStreamInfo
virtual uint16_t GetStreamInfo(void) const
Definition: ancillarydata.cpp:223
LOGMYERROR
#define LOGMYERROR(__x__)
Definition: ancillarydata.cpp:25
AJAAncDataChannel_C
@ AJAAncDataChannel_C
The ancillary data is associated with the chrominance (C) channel of the video stream.
Definition: ancillarydata.h:131
HEX0N
#define HEX0N(__x__, __n__)
Definition: debug.cpp:1175
AJAAncillaryData::operator=
AJAAncillaryData & operator=(const AJAAncillaryData &inRHS)
Definition: ancillarydata.cpp:1575
operator<<
ostream & operator<<(ostream &inOutStream, const AJAAncDataLoc &inValue)
Definition: ancillarydata.cpp:1365
AJAAncillaryData::ParsePayloadData
virtual AJAStatus ParsePayloadData(void)
Parses (interprets) the "local" ancillary data from my payload data.
Definition: ancillarydata.cpp:501
LOGMYDEBUG
#define LOGMYDEBUG(__x__)
Definition: ancillarydata.cpp:29
AJAAncillaryData::GetNumConstructed
static uint32_t GetNumConstructed(void)
Definition: ancillarydata.cpp:1999
AJAAncDataTypeToString
const string & AJAAncDataTypeToString(const AJAAncDataType inValue, const bool inCompact)
Definition: ancillarydata.cpp:1390
std
Definition: json.hpp:5362
AJAAncillaryData::operator==
virtual bool operator==(const AJAAncillaryData &inRHS) const
Definition: ancillarydata.cpp:1599
AJAStatusToString
std::string AJAStatusToString(const AJAStatus inStatus, const bool inDetailed)
Definition: debug.cpp:981
XMT2110WARN
#define XMT2110WARN(__x__)
Definition: ancillarydata.cpp:38
AJAAncDataLoc::Print
std::ostream & Print(std::ostream &ostrm, const bool inCompact=true) const
Writes a human-readable rendition of me into the given output stream.
Definition: ancillarydata.cpp:1306
ULWordSequence
std::vector< uint32_t > ULWordSequence
An ordered sequence of ULWord (uint32_t) values.
Definition: ntv2publicinterface.h:46
XMT2110DBG
#define XMT2110DBG(__x__)
Definition: ancillarydata.cpp:41
AncChannelSearchSelect
AncChannelSearchSelect
Specifies which channel of a video stream in which to look for Anc data.
Definition: ancillarydata.h:152
AJAAncDataLoc::SetDataLink
AJAAncDataLoc & SetDataLink(const AJAAncDataLink inLink)
Sets my data link value to the given value (if valid).
Definition: ancillarydata.h:354
AJAAncillaryData::FreeDataMemory
AJAStatus FreeDataMemory(void)
Definition: ancillarydata.cpp:193
AJARTPAncPacketHeader::SetFromULWord
virtual bool SetFromULWord(const uint32_t inULWord)
Resets my current state by decoding the given 4-byte header value.
Definition: ancillarydata.cpp:2414
AJAAncillaryData::GetPayloadByteAtIndex
virtual uint8_t GetPayloadByteAtIndex(const uint32_t inIndex0) const
Definition: ancillarydata.cpp:482
atomic.h
Declares the AJAAtomic class.
AJAAncillaryDataWrapperSize
const uint32_t AJAAncillaryDataWrapperSize
Definition: ancillarydata.cpp:81
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:766
AJAAncillaryData::AddEvenParity
static uint16_t AddEvenParity(const uint8_t inDataByte)
Definition: ancillarydata.cpp:1606
AJAAncillaryData::Clone
virtual AJAAncillaryData * Clone(void) const
Definition: ancillarydata.cpp:165
LOGMYINFO
#define LOGMYINFO(__x__)
Definition: ancillarydata.cpp:28
AJAAncLineNumberToString
string AJAAncLineNumberToString(const uint16_t inValue)
Definition: ancillarydata.cpp:1270
AJAAncDataCoding_Digital
@ AJAAncDataCoding_Digital
The ancillary data is in the form of a SMPTE-291 Ancillary Packet.
Definition: ancillarydata.h:476
gIndexes
static const size_t gIndexes[]
Definition: ancillarydata.cpp:923
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:1536
AJARTPAncPayloadHeader::BufferStartsWithRTPHeader
static bool BufferStartsWithRTPHeader(const NTV2Buffer &inBuffer)
Definition: ancillarydata.cpp:2171
AJAAncDataCoding
AJAAncDataCoding
Identifies the ancillary data coding type: digital or non-digital (analog/raw).
Definition: ancillarydata.h:474
DIDSIDToStringMap
map< AJAAncDIDSIDPair, string > DIDSIDToStringMap
Definition: ancillarydata.cpp:2020
AJAAncBufferFormat
AJAAncBufferFormat
Identifies the type of anc buffer the packet originated from: GUMP, RTP, VANC, or unknown.
Definition: ancillarydata.h:496
AJAAncDataStreamToString
const string & AJAAncDataStreamToString(const AJAAncDataStream inValue, const bool inCompact)
Definition: ancillarydata.cpp:1242
AJAAncDataHorizOffset_Unknown
#define AJAAncDataHorizOffset_Unknown
Unknown.
Definition: ancillarydata.h:209
AJAAncBufferFormat_RTP
@ AJAAncBufferFormat_RTP
RTP/IP.
Definition: ancillarydata.h:501
IS_LINKB_AJAAncDataStream
#define IS_LINKB_AJAAncDataStream(_x_)
Definition: ancillarydata.h:115
IsRaw
bool IsRaw(const NTV2FrameBufferFormat format)
Definition: ntv2utils.cpp:5511
AJARTPAncPayloadHeader::IsValid
virtual bool IsValid(void) const
Definition: ancillarydata.cpp:2365
AJAAncillaryData::m_auxHB1
uint8_t m_auxHB1
HDMI Aux Header Byte 1 (Header Data)
Definition: ancillarydata.h:1165
ntv2publicinterface.h
Declares enums and structs used by all platform drivers and the SDK.
AJAAncDataLoc::SetDataChannel
AJAAncDataLoc & SetDataChannel(const AJAAncDataChannel inChannel)
Sets my data video stream value to the given value (if valid).
Definition: ancillarydata.h:368
AJAAncDataSpace_VANC
@ AJAAncDataSpace_VANC
Ancillary data found between SAV and EAV (.
Definition: ancillarydata.h:177
AJAAncillaryData::SetFromSMPTE334
virtual AJAStatus SetFromSMPTE334(const uint16_t *pInData, const uint32_t inNumWords, const AJAAncDataLoc &inLocInfo)
Copies payload data from an external 16-bit source into local payload memory.
Definition: ancillarydata.cpp:370
AJAAncillaryData::m_ancType
AJAAncDataType m_ancType
One of a known set of ancillary data types (or "Custom" if not identified)
Definition: ancillarydata.h:1159
AJAAncillaryData::SetPayloadByteAtIndex
virtual AJAStatus SetPayloadByteAtIndex(const uint8_t inDataByte, const uint32_t inIndex0)
Definition: ancillarydata.cpp:491
AJARTPAncPacketHeader::Print
virtual std::ostream & Print(std::ostream &inOutStream) const
Streams a human-readable represetation of my current state to the given output stream.
Definition: ancillarydata.cpp:2495
NTV2DIDSet
std::set< UByte > NTV2DIDSet
A set of distinct NTV2DID values.
Definition: ntv2publicinterface.h:76
AJAAncBufferFormat_Unknown
@ AJAAncBufferFormat_Unknown
Unknown or "don't care".
Definition: ancillarydata.h:498
BIT
#define BIT(_x_)
Definition: ajatypes.h:563
xHEX0N
#define xHEX0N(__x__, __n__)
Definition: ntv2publicinterface.h:5693
AJA_FAILURE
#define AJA_FAILURE(_status_)
Definition: types.h:371
AJAAncBufferFormatToString
const string & AJAAncBufferFormatToString(const AJAAncBufferFormat inValue, const bool inCompact)
Definition: ancillarydata.cpp:1380
RCV2110WARN
#define RCV2110WARN(__x__)
Definition: ancillarydata.cpp:32
AJARTPAncPacketHeader::SetHorizOffset
virtual AJARTPAncPacketHeader & SetHorizOffset(const uint16_t inHOffset)
Sets my horizontal offset value to least-significant 12 bits of the given value.
Definition: ancillarydata.h:1494
gEmptyString
static const string gEmptyString
Definition: ancillarydata.cpp:1230
AJAAuxillaryPacketSize
const uint32_t AJAAuxillaryPacketSize
Definition: ancillarydata.cpp:82
AJAAncDataLink_A
@ AJAAncDataLink_A
The ancillary data is associated with Link A of the video stream.
Definition: ancillarydata.h:81
AJARTPAncPacketHeader::SetStreamNumber
virtual AJARTPAncPacketHeader & SetStreamNumber(const uint8_t inStreamNum)
Sets my stream number value to least-significant 7 bits of the given value.
Definition: ancillarydata.h:1502
AJAAncillaryData::U16Packets
std::vector< U16Packet > U16Packets
An ordered sequence of zero or more U16Packet values.
Definition: ancillarydata.h:1062
AJAAncillaryData::ResetInstanceCounts
static void ResetInstanceCounts(void)
Definition: ancillarydata.cpp:1983
RCV2110DDBG
#define RCV2110DDBG(__x__)
Definition: ancillarydata.cpp:54
AJAAncDataHorizOffset_Future
#define AJAAncDataHorizOffset_Future
Offset exceeds 12 bits (future).
Definition: ancillarydata.h:213
AJAAncillaryData::AuxPacketTypeIsValid
static bool AuxPacketTypeIsValid(const uint8_t inAuxPktType)
Definition: ancillarydata.cpp:2162
debug.h
Declares the AJADebug class.
AJAAncillaryData::U16Packet
UWordSequence U16Packet
An ordered sequence of 10-bit packet words stored in uint16_t values.
Definition: ancillarydata.h:1061
AJARTPAncPayloadHeader::Print
virtual std::ostream & Print(std::ostream &inOutStream) const
Writes a human-readable dump of my current state into a given output stream.
Definition: ancillarydata.cpp:2345
AJAAncillaryData::m_checksum
uint8_t m_checksum
My 8-bit checksum: DID + SID + DC + payload (w/o parity) [note: NOT the same as the 9-bit checksum in...
Definition: ancillarydata.h:1154
AJAAncillaryData::SetLocationDataChannel
virtual AJAStatus SetLocationDataChannel(const AJAAncDataChannel inChannel)
Sets my ancillary data "location" data channel value (Y or C).
Definition: ancillarydata.cpp:309
AncChannelSearch_Both
@ AncChannelSearch_Both
Look both luma and chroma samples (SD only)
Definition: ancillarydata.h:156
AJARTPAncPacketHeader::GetULWord
virtual uint32_t GetULWord(void) const
Definition: ancillarydata.cpp:2395
AJARTPAncPayloadHeader::GetPacketHeaderULWordForIndex
virtual bool GetPacketHeaderULWordForIndex(const unsigned inIndex0, uint32_t &outULWord) const
Answers with the 32-bit RTP packet header value for the given position. The returned value will be in...
Definition: ancillarydata.cpp:2198
AJAAncillaryData::Init
void Init(void)
Definition: ancillarydata.cpp:131
AncChannelSearch_Y
@ AncChannelSearch_Y
Only look in luma samples.
Definition: ancillarydata.h:154
AJAAncillaryData::DumpPayload
virtual std::ostream & DumpPayload(std::ostream &inOutStream) const
Dumps a human-readable representation of my payload bytes into the given output stream.
Definition: ancillarydata.cpp:1480