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