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