AJA NTV2 SDK  17.1.1.1245
NTV2 SDK 17.1.1.1245
ancillarydata_cea608_line21.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
9 #include <ios>
10 #include <iomanip>
11 
12 using namespace std;
13 
14 
16 {
17  Init();
18 }
19 
20 
22 {
23  Init();
24 
25  *this = clone;
26 }
27 
28 
30 {
31  Init();
32 
33  if (pClone != NULL_PTR)
34  *this = *pClone;
35 }
36 
37 
39 {
40  Init();
41 }
42 
43 
45 {
46 }
47 
48 
50 {
57  if (GetLocationLineNumber() == 0) // If not already set...
58  SetLocationLineNumber(21); // ...then assume F1, otherwise SetLocationLineNumber(284);
59 }
60 
61 
63 {
64  if (this != &rhs) // ignore self-assignment
65  {
66  AJAAncillaryData_Cea608::operator= (rhs); // copy the base class stuff
67 
68  // copy the local stuff
71  }
72  return *this;
73 }
74 
75 
77 {
79  Init();
80 }
81 
82 
84 {
85  if (IsEmpty())// || m_DC != AJAAncillaryData_Cea608_Line21_PayloadSize)
86  {
87  Init(); // load default values
88  return AJA_STATUS_FAIL;
89  }
90 
91  // we have some kind of payload data - try to parse it
92  uint8_t char1(0), char2(0);
93  bool bGotClock (false);
94  m_rcvDataValid = false;
95  AJAStatus status = DecodeLine (char1, char2, bGotClock);
96  if (AJA_SUCCESS(status) && bGotClock)
97  {
98  m_char1 = char1;
99  m_char2 = char2;
100  m_rcvDataValid = true;
101  }
102  return status;
103 }
104 
105 
106 const uint32_t CC_DEFAULT_ENCODE_OFFSET = 7; // number of pixels between start of buffer and beginning of first CC bit-cell
107 
109 {
110  AJAStatus status (AJA_STATUS_SUCCESS);
111 
114 
115  // the first time through we're going to allocate the payload data and initialize the "unchanging" pixels
116  // (run-in clock, etc.). After that we're going to assume: (a) the payload size never changes; and (b) the
117  // unchanging bits don't change.
119  status = AllocEncodeBuffer();
120 
121  // encode the payload data
122  if (AJA_SUCCESS(status))
124 
125  // note: we're not going to bother with a checksum since it's tedious and the hardware ignores it anyway...
126  return status;
127 }
128 
129 
131 {
133  if (AJA_SUCCESS(status))
134  {
135  // init the buffer with all of the "static" stuff (run-in clock, pre- and post- black, etc.)
137  if (AJA_SUCCESS(status))
139  }
140  return status;
141 }
142 
143 
145 {
146  // BIG ASSUMPTION! If the user deliberately captured analog line 21 on either field,
147  // we're assuming it was for the sake of getting captioning data (NTSC/525-line).
148  // The only way we could know "for sure" would be to run ParsePayloadData() on
149  // the payload data, but that's not a static method so you'd have to recast the
150  // AJAAncillaryData object anyway!
151  if (pInAncData->GetDataCoding() == AJAAncDataCoding_Raw)
152  if (pInAncData->GetLocationLineNumber() == 21 || pInAncData->GetLocationLineNumber() == 284)
154  return AJAAncDataType_Unknown;
155 }
156 
157 
158 //-------------------------------------------------------------
159 // Line 21 Encode code (ported/stolen from ntv2closedcaptioning.cpp)
160 
161 
162 //--------------------------------------------------------
163 // Encode
164 
165 // This module can be used to encode two ASCII characters to a line 21 closed captioning
166 // waveform, or conversely decode a line 21 waveform to the two characters it contains.
167 // This is NOT a general module: it assumes a 720-pixel line (e.g. Standard Definition "NTSC"),
168 // and that the closed captioning is represented by an EIA-608 waveform.
169 
170 // This implementation only handles conversion to/from 8-bit uncompressed ('2vuy') video.
171 
172 // NOTE: this implementation makes a simplifying assumption that all captioning bits
173 // are 27 pixels wide. This is a cheat: the actual bit duration should be (H / 32), which
174 // for NTSC video is 858 pixels / 32 = 26.8125 pixels per bit. This difference should be
175 // within the tolerance of most captioning receivers, but beware - we may find that in
176 // practice we need more precision someday. (Note that in PAL the line width is 864 pixels,
177 // which is exactly 27.0 pixels/bit).
178 
179 const uint8_t CC_BIT_WIDTH = 27; // = round(858 / 32)
180 const uint8_t CC_LEVEL_LO = 16; // '0' bit level
181 const uint8_t CC_LEVEL_HI = 126; // '1' bit level
182 const uint8_t CC_LEVEL_MID = 71; // "slice" level - mid-way between '0' and '1'
183 const uint8_t CC_LEVEL_TRANS = 20;
184 
185 
186 // Funny math: there are exactly 7 cycles of Clock Run-In, which is an inverted cosine wave.
187 // Each cycle is the same duration as one CC bit (27 pixels). HOWEVER, the CC bit edges are
188 // supposed to be coincident with the 50% point of the trailing edge of each clock cycle
189 // (think of it as 270 degrees through the cycle), while the actual clock run-in cycles are
190 // generated from 0 degrees to 0 degrees. So the first clock cycle begins 90 degrees into the
191 // first "bit", and the last clock cycle draws its last 90 degrees overlapping into the first
192 // zero start bit. This value is the "length" of this 90 degree offset in pixels.
193 const uint32_t CLOCK_RUN_IN_OFFSET = 7; // number of pixels in 90 degrees
194 
195 // the transition time between low and high ("rise-time") and high to low ("fall time") is
196 // three samples. Since bit cells start and end at the 50% points, some of the transition
197 // samples belong to the previous bit, and some belong to the next bit.
198 const uint32_t TRANSITION_PRE = 1; // one sample of the transition "belongs" to the previous bit
199 const uint32_t TRANSITION_POST = 2; // two samples of the transition "belong" to the next bit
201 
202 
203 // Initialize a prototype Line 21 buffer with the parts that DON'T change:
204 // i.e. the Clock Run-In and the Start bits.
205 AJAStatus AJAAncillaryData_Cea608_Line21::InitEncodeBuffer (uint32_t lineStartOffset, uint32_t & dataStartOffset)
206 {
207  // 1 cycle of the Line 21 Clock Run-In (see note in header file about freq. approximation)
208  static const uint8_t cc_clock[27] = { 16, 17, 22, 29, 38, 49, 61, 74, 86, 98, 108, 116, 122, 125,
209  125, 122, 116, 108, 98, 86, 74, 61, 49, 38, 29, 22, 17 };
210 
211  // sanity check...
213  return AJA_STATUS_FAIL;
214 
215  AJAStatus status = AJA_STATUS_SUCCESS;
216 
217  uint32_t i, j;
218  ByteVectorIndex pos(0);
219  const uint8_t kSMPTE_Y_Black (0x10);
220 
221  // fill Black until beginning of Clock Run-In
222  // both the user-supplied offset to the first bit-cell, plus the "missing" quarter-cycle of the clock
223  for (i = 0; i < (lineStartOffset + CLOCK_RUN_IN_OFFSET); i++)
224  m_payload[pos++] = kSMPTE_Y_Black; // Note: assuming SMPTE "Y" black!
225 
226  // 7 cycles of 503,496 Hz clock run-in
227  for (j = 0; j < 7; j++)
228  for (i = 0; i < CC_BIT_WIDTH; i++)
229  m_payload[pos++] = cc_clock[i]; // clock
230 
231  // Start bit: 1 CC bits of '0' (reduced width because the last cycle of the clock run-in overlaps)
232  for (i = 0; i < (CC_BIT_WIDTH - CLOCK_RUN_IN_OFFSET); i++)
233  m_payload[pos++] = CC_LEVEL_LO;
234 
235  // Start bit: 1 CC bit of '0' (full width)
236  for (i = 0; i < CC_BIT_WIDTH - TRANSITION_POST; i++)
237  m_payload[pos++] = CC_LEVEL_LO;
238 
239  // encode transition between low and high
240  EncodeTransition (&m_payload[pos], 0, 1);
241  pos += TRANSITION_WIDTH;
242 
243  // Start bit: 1 CC bit of '1'
244  for (i = 0; i < CC_BIT_WIDTH - TRANSITION_PRE; i++)
245  m_payload[pos++] = CC_LEVEL_HI;
246 
247  // Fill in black for the rest of the buffer - this will be overwritten with "real" data bits later
248  while (pos < GetDC())
249  m_payload[pos++] = kSMPTE_Y_Black; // Note: assuming SMPTE "Y" black!
250 
251  // the first data bit cell starts 10 bit cells after the initial offset
252  // (note: does NOT include slop for needed rise-time)
253  dataStartOffset = lineStartOffset + (10 * CC_BIT_WIDTH);
254 
255  return status;
256 }
257 
258 
259 // encodes the supplied two bytes into the existing encode buffer and returns a pointer to same
260 // note: caller should NOT modify the returned buffer in any way.
261 AJAStatus AJAAncillaryData_Cea608_Line21::EncodeLine (uint8_t char1, uint8_t char2, uint32_t dataStartOffset)
262 {
263  // pointer to first data bit, minus room for transition
264  uint8_t *ptr = &m_payload[0] + (dataStartOffset - TRANSITION_PRE);
265 
266  // encode transition from last start bit to first bit of first character
267  ptr = EncodeTransition (ptr, 1, (char1 & 0x01) );
268 
269  // encode first byte
270  ptr = EncodeCharacter (ptr, char1);
271 
272  // encode transition between characters
273  ptr = EncodeTransition (ptr, (char1 & 0x80), (char2 & 0x01) );
274 
275  // encode second byte
276  ptr = EncodeCharacter (ptr, char2);
277 
278  // encode final transition
279  ptr = EncodeTransition (ptr, (char2 & 0x80), 0);
280 
281  // return ptr to the beginning of the encode buffer
282  return AJA_STATUS_SUCCESS;
283 }
284 
285 
286 // encodes from the end of the transition to the first bit until the start of the transition from the last bit
287 // returns the pointer to the next pixel following the character (i.e. the beginning of the transition to the next character)
288 // Note: the ms bit is supposed to be odd parity for the ls 7 bits. It is up to the caller to make this so.
289 uint8_t * AJAAncillaryData_Cea608_Line21::EncodeCharacter (uint8_t * ptr, uint8_t byte)
290 {
291  uint8_t mask = 1;
292 
293  // do all 8 bits
294  for (uint8_t j = 0; j < 8; j++)
295  {
296  // do the constant samples
297  uint8_t level = ((byte & mask) == 0) ? CC_LEVEL_LO : CC_LEVEL_HI;
298 
299  for (uint32_t i = 0; i < (CC_BIT_WIDTH - TRANSITION_WIDTH); i++)
300  *ptr++ = level;
301 
302  // do the transition (except following the last bit)
303  uint8_t nextMask = mask << 1;
304 
305  if (j < 7)
306  ptr = EncodeTransition(ptr, (byte & mask), (byte & nextMask) );
307 
308  mask = nextMask;
309  }
310  return ptr;
311 }
312 
313 // encodes from the beginning of the transition of one bit ("inStartLevel") to the next ("inEndLevel")
314 // returns the pointer to the next pixel following the transition
315 uint8_t * AJAAncillaryData_Cea608_Line21::EncodeTransition (uint8_t * ptr, const uint8_t inStartLevel, const uint8_t inEndLevel)
316 {
317  // 4 possible transition types:
318  static const uint8_t cc_trans_lo_lo[TRANSITION_WIDTH] = { CC_LEVEL_LO, CC_LEVEL_LO, CC_LEVEL_LO }; // Low -> Low
319  static const uint8_t cc_trans_lo_hi[TRANSITION_WIDTH] = { CC_LEVEL_LO+CC_LEVEL_TRANS, CC_LEVEL_MID, CC_LEVEL_HI-CC_LEVEL_TRANS }; // Low -> High
320  static const uint8_t cc_trans_hi_lo[TRANSITION_WIDTH] = { CC_LEVEL_HI-CC_LEVEL_TRANS, CC_LEVEL_MID, CC_LEVEL_LO+CC_LEVEL_TRANS }; // High -> Low
321  static const uint8_t cc_trans_hi_hi[TRANSITION_WIDTH] = { CC_LEVEL_HI, CC_LEVEL_HI, CC_LEVEL_HI }; // High -> High
322 
323  const uint8_t * pTrans (NULL);
324 
325  if (inStartLevel == 0 && inEndLevel == 0)
326  pTrans = cc_trans_lo_lo;
327  else if (inStartLevel == 0 && inEndLevel != 0)
328  pTrans = cc_trans_lo_hi;
329  else if (inStartLevel != 0 && inEndLevel == 0)
330  pTrans = cc_trans_hi_lo;
331  else
332  pTrans = cc_trans_hi_hi;
333 
334  for (uint32_t i = 0; i < TRANSITION_WIDTH; i++)
335  *ptr++ = pTrans[i];
336 
337  return ptr;
338 }
339 
340 
341 //--------------------------------------------------------
342 // Decode
343 
344 // Decodes the supplied line of 8-bit uncompressed ('2vuy') data and, if successful, returns the
345 // two 8-bit characters in *pChar1 (first character) and *pChar2 (second character).
346 // Note: this routine does not try to analyze the characters in any way - including trying to
347 // do parity checks. If desired, that is the responsibility of the caller. This routine WILL
348 // try to make a reasonable attempt to discover whether captioning data is present or not,
349 // and if it decides that the line does NOT contain encoded captioning info, will return 'false'
350 // and set the characters to 0.
351 AJAStatus AJAAncillaryData_Cea608_Line21::DecodeLine (uint8_t & outChar1, uint8_t & outChar2, bool & outGotClock) const
352 {
353  outChar1 = outChar2 = 0xFF;
354  outGotClock = false;
356  return AJA_STATUS_FAIL;
357 
358  // see if the line contains a captioning clock run-in, signifying a valid captioning line
359  // If successful, CheckDecodeClock will return a pointer to the middle of the first data
360  // bit (i.e. the one following the last '1' start bit) and will set outGotClock to 'true'.
361  // If CheckDecodeClock cannot find a valid clock run-in, it will return with outGotClock
362  // set to 'false'.
363  const uint8_t * pFirstDataBit = CheckDecodeClock (GetPayloadData(), outGotClock);
364  if (outGotClock)
365  return DecodeCharacters(pFirstDataBit, outChar1, outChar2); // decode characters
366 
367  // note: we're NOT returning an error if no clock was found. In fact, this is a fairly
368  // normal happening (a lot of programs are not captioned), so the caller should be sure
369  // to check bGotClock upon return to make sure the returned characters are valid.
370  return AJA_STATUS_SUCCESS;
371 }
372 
373 
374 const uint8_t * AJAAncillaryData_Cea608_Line21::CheckDecodeClock (const uint8_t * pInLine, bool & bGotClock)
375 {
376  bGotClock = false; // assume the worst...
377  if (!pInLine)
378  return NULL;
379 
380  const uint8_t *pFirstYSample = pInLine; // point to first pixel in line
381  const uint8_t *pFirstClockEdge = NULL;
382  const uint8_t *pLastClockEdge = NULL;
383  const uint8_t *pFirstDataBit = pFirstYSample;
384 
385  // The rising edge of the first clock run-in cycle should happen approx 10.5 usecs from the leading
386  // edge of sync, which translates to approx. 20 pixels from the left-hand edge of active video.
387  // However, the tolerance on this value is +/- 500 nsec, or +/- 7 pixels. So we need to programatically
388  // find the first leading clock edge and use that as our reference.
389 
390  // Start looking for a low->high transition starting at pixel 10, give up if we haven't found it by pixel 30.
391  uint32_t pos(0);
392  uint32_t startSearch = 10;
393  uint32_t stopSearch = 30;
394  for (pos = startSearch; pos < stopSearch; pos++)
395  if (pFirstYSample[pos] < CC_LEVEL_MID && pFirstYSample[pos+1] >= CC_LEVEL_MID)
396  break;
397 
398  // did we find it?
399  if (pos < stopSearch)
400  {
401  pFirstClockEdge = &pFirstYSample[pos];
402 // cerr << "AJAAncillaryData_Cea608_Line21::CheckDecodeClock: found first clock edge at pixel " << i << endl;
403 
404  // if this is the leading edge of the first sine wave, then the crest of this wave will
405  // be approx 7 pixels from here, and the trough of this wave will be approx 13 clocks after that.
406  // This pattern will repeat every 27 pixels for 7 cycles.
407  for (pos = 0; pos < 7; pos++)
408  {
409  uint32_t hi = (pos * CC_BIT_WIDTH) + 7;
410  uint32_t lo = (pos * CC_BIT_WIDTH) + 20;
411 
412  if ( (pFirstClockEdge[hi] < CC_LEVEL_MID) || (pFirstClockEdge[lo] >= CC_LEVEL_MID) )
413  break;
414  }
415 
416  if (pos < 7)
417  {
418  // Failed to find an expected clock crest or trough - abort
419 // cerr << "AJAAncillaryData_Cea608_Line21::CheckDecodeClock: failed clock run-in test at cycle " << pos << endl;
420  }
421  else
422  {
423 // cerr << "AJAAncillaryData_Cea608_Line21::CheckDecodeClock: confirmed 7 cycles of clock run-in" << endl;
424 
425  // the 7 cycles of clock looks OK, now let's specifically find the leading edge
426  // of the last clock. This will serve as our reference sample point for the data bits
427  startSearch = (5 * CC_BIT_WIDTH) + 20; // the lo point of the 6th cycle
428  stopSearch = (6 * CC_BIT_WIDTH) + 7; // the hi point of the 7th cycle
429  for (pos = startSearch; pos < stopSearch; pos++)
430  {
431  if ( (pFirstClockEdge[pos] < CC_LEVEL_MID) && (pFirstClockEdge[pos+1] >= CC_LEVEL_MID) )
432  break;
433  }
434 
435  // the mid-point of each sample bit will occur on bit-cell multiples from here
436  pLastClockEdge = &pFirstClockEdge[pos+1];
437 // cerr << "AJAAncillaryData_Cea608_Line21::CheckDecodeClock: leading edge of last clock cycle at pixel " << uint64_t(pLastClockEdge - pFirstYSample) << endl;
438 
439  // the next three bit cells are the start bits, which should be 0, 0, 1
440  if ( (pLastClockEdge[(CC_BIT_WIDTH * 1)] < CC_LEVEL_MID)
441  && (pLastClockEdge[(CC_BIT_WIDTH * 2)] < CC_LEVEL_MID)
442  && (pLastClockEdge[(CC_BIT_WIDTH * 3)] >= CC_LEVEL_MID) )
443  {
444  // so we have to assume we're good to go! Return the mid-point of the first data bit
445  // past the last start bit
446  pFirstDataBit = &pLastClockEdge[(CC_BIT_WIDTH * 4)];
447 
448 // cerr << "AJAAncillaryData_Cea608_Line21::CheckDecodeClock: start bits correct, first data bit at pixel " << uint64_t(pFirstDataBit - pFirstYSample) << endl;
449  bGotClock = true;
450  }
451  else
452  {
453 // cerr << "AJAAncillaryData_Cea608_Line21::CheckDecodeClock: bad start bits: "
454 // << pLastClockEdge[(CC_BIT_WIDTH * 1)] >= CC_LEVEL_MID << ", "
455 // << pLastClockEdge[(CC_BIT_WIDTH * 2)] >= CC_LEVEL_MID << ", "
456 // << pLastClockEdge[(CC_BIT_WIDTH * 3)] >= CC_LEVEL_MID << endl;
457  }
458  }
459  }
460 // else cerr << "AJAAncillaryData_Cea608_Line21::CheckDecodeClock: couldn't find first clock edge" << endl;
461 
462  return pFirstDataBit;
463 }
464 
465 
466 // call with ptr set to mid-point of first data bit (i.e. the one following the '1' start bit)
467 // This method will read the two characters and return 'true' if successful.
468 // Note: this routine will return the parity bit of each character in the ms bit position. It
469 // makes no calculation or value judgment as to the correctness of the parity.
470 AJAStatus AJAAncillaryData_Cea608_Line21::DecodeCharacters (const uint8_t *ptr, uint8_t & outChar1, uint8_t & outChar2)
471 {
472  // first character, ls bit first
473  outChar1 = 0;
474  for (uint8_t i = 0; i < 8; i++)
475  {
476  const uint8_t bit ((ptr[i * CC_BIT_WIDTH] > CC_LEVEL_MID) ? 1 : 0);
477  outChar1 += (bit << i);
478  }
479 
480  // advance ptr to middle of first data bit in second character
481  ptr += (8 * CC_BIT_WIDTH);
482 
483  // second character, ls bit first
484  outChar2 = 0;
485  for (uint8_t i = 0; i < 8; i++)
486  {
487  const uint8_t bit ((ptr[i * CC_BIT_WIDTH] > CC_LEVEL_MID) ? 1 : 0);
488  outChar2 += (bit << i);
489  }
490 
491 #if 0 // debug
492  if (char1 == 0x80 && char2 == 0x80)
493  cerr << "--- AJAAncillaryData_Cea608_Line21::DecodeCharacters: returned NULL" << endl;
494  else if (((outChar1 & 0x7f) >= 0x20) && ((outChar2 & 0x7f) >= 0x20))
495  cerr << "--- AJAAncillaryData_Cea608_Line21::DecodeCharacters: returned '" << (outChar1 & 0x7f) << "' '" << (outChar2 & 0x7f) << endl;
496  else
497  cerr << "--- AJAAncillaryData_Cea608_Line21::DecodeCharacters: returned " << xHEX0N(outChar1,2) << " " << xHEX0N(outChar2) << endl;
498 #endif
499  return AJA_STATUS_SUCCESS;
500 }
CLOCK_RUN_IN_OFFSET
const uint32_t CLOCK_RUN_IN_OFFSET
Definition: ancillarydata_cea608_line21.cpp:193
NULL_PTR
#define NULL_PTR
Definition: types.h:325
AJAAncillaryData_Cea608_Line21::CheckDecodeClock
static const uint8_t * CheckDecodeClock(const uint8_t *pInLine, bool &outGotClock)
Checks for the existence of a CEA-608 "analog" waveform and, if found, returns a pointer to the start...
Definition: ancillarydata_cea608_line21.cpp:374
AJAAncillaryData_Cea608_Line21_PayloadSize
const uint32_t AJAAncillaryData_Cea608_Line21_PayloadSize
Definition: ancillarydata_cea608_line21.h:20
AJAAncillaryData_Cea608_Line21::EncodeLine
virtual AJAStatus EncodeLine(const uint8_t inChar1, const uint8_t inChar2, const uint32_t inDataStartOffset)
Encode and insert the given 8-bit characters into the (already initialized) payload buffer.
Definition: ancillarydata_cea608_line21.cpp:261
AJAAncillaryData::m_DID
uint8_t m_DID
Official SMPTE ancillary packet ID (w/o parity)
Definition: ancillarydata.h:1152
ancillarydata_cea608_line21.h
Declares the AJAAncillaryData_Cea608_line21 class.
AJAAncDataType_Unknown
@ AJAAncDataType_Unknown
Includes data that is valid, but we don't recognize.
Definition: ancillarydata.h:46
AJAAncillaryData_Cea608_Line21::Clear
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values.
Definition: ancillarydata_cea608_line21.cpp:76
NULL
#define NULL
Definition: ntv2caption608types.h:19
AJA_STATUS_SUCCESS
@ AJA_STATUS_SUCCESS
Definition: types.h:381
AJAAncillaryData::ByteVectorIndex
ByteVector::size_type ByteVectorIndex
Definition: ancillarydata.h:1138
AJAAncillaryData_Cea608::Clear
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values.
Definition: ancillarydata_cea608.cpp:71
AJAAncillaryData_Cea608_Line21
This class handles "analog" (Line 21) based CEA-608 caption data packets.
Definition: ancillarydata_cea608_line21.h:27
CC_LEVEL_HI
const uint8_t CC_LEVEL_HI
Definition: ancillarydata_cea608_line21.cpp:181
TRANSITION_POST
const uint32_t TRANSITION_POST
Definition: ancillarydata_cea608_line21.cpp:199
AJAAncillaryData_Cea608_Line21_SID
const uint8_t AJAAncillaryData_Cea608_Line21_SID
Definition: ancillarydata_cea608_line21.h:18
AJAAncDataType
AJAAncDataType
Identifies the ancillary data types that are known to this module.
Definition: ancillarydata.h:44
AJAAncillaryData::AllocDataMemory
AJAStatus AllocDataMemory(const uint32_t inNumBytes)
Definition: ancillarydata.cpp:171
AJAAncillaryData_Cea608_Line21::m_dataStartOffset
uint32_t m_dataStartOffset
Offset into the encode buffer where data starts.
Definition: ancillarydata_cea608_line21.h:168
AJAAncillaryData_Cea608_Line21::~AJAAncillaryData_Cea608_Line21
virtual ~AJAAncillaryData_Cea608_Line21()
My destructor.
Definition: ancillarydata_cea608_line21.cpp:44
AJAAncDataCoding_Raw
@ AJAAncDataCoding_Raw
The ancillary data is in the form of a digitized waveform (e.g. CEA-608 captions, VITC,...
Definition: ancillarydata.h:477
AJAAncillaryData_Cea608_Line21::DecodeCharacters
static AJAStatus DecodeCharacters(const uint8_t *ptr, uint8_t &outChar1, uint8_t &outChar2)
Decodes the two CEA-608 data characters for this line.
Definition: ancillarydata_cea608_line21.cpp:470
AJAAncillaryData_Cea608_Line21::EncodeTransition
virtual uint8_t * EncodeTransition(uint8_t *ptr, const uint8_t inStartLevel, const uint8_t inEndLevel)
Encodes a single bit transition from the "from" level to the "to" level.
Definition: ancillarydata_cea608_line21.cpp:315
AJAStatus
AJAStatus
Definition: types.h:378
AJAAncillaryData_Cea608_Line21::RecognizeThisAncillaryData
static AJAAncDataType RecognizeThisAncillaryData(const AJAAncillaryData *pInAncData)
Definition: ancillarydata_cea608_line21.cpp:144
AJA_STATUS_FAIL
@ AJA_STATUS_FAIL
Definition: types.h:382
AJAAncillaryData_Cea608
This is the base class for handling CEA-608 caption data packets.
Definition: ancillarydata_cea608.h:18
AJAAncillaryData_Cea608_Line21::m_bEncodeBufferInitialized
bool m_bEncodeBufferInitialized
Set 'true' after successfully allocating and initializing the m_payload buffer for encoding.
Definition: ancillarydata_cea608_line21.h:167
AJAAncillaryData
I am the principal class that stores a single SMPTE-291 SDI ancillary data packet OR the digitized co...
Definition: ancillarydata.h:552
AJAAncillaryData_Cea608_Line21::AllocEncodeBuffer
virtual AJAStatus AllocEncodeBuffer(void)
Definition: ancillarydata_cea608_line21.cpp:130
AJAAncillaryData::GetPayloadData
virtual const uint8_t * GetPayloadData(void) const
Definition: ancillarydata.h:801
AJAAncillaryData_Cea608_Line21::AJAAncillaryData_Cea608_Line21
AJAAncillaryData_Cea608_Line21()
My default constructor.
Definition: ancillarydata_cea608_line21.cpp:15
AJAAncillaryData_Cea608_Line21::ParsePayloadData
virtual AJAStatus ParsePayloadData(void)
Parses out (interprets) the "local" ancillary data from my payload data.
Definition: ancillarydata_cea608_line21.cpp:83
CC_BIT_WIDTH
const uint8_t CC_BIT_WIDTH
Definition: ancillarydata_cea608_line21.cpp:179
CC_LEVEL_LO
const uint8_t CC_LEVEL_LO
Definition: ancillarydata_cea608_line21.cpp:180
AJAAncillaryData::m_coding
AJAAncDataCoding m_coding
Analog or digital data.
Definition: ancillarydata.h:1156
AJAAncillaryData_Cea608_Line21::DecodeLine
virtual AJAStatus DecodeLine(uint8_t &outChar1, uint8_t &outChar2, bool &outGotClock) const
Decodes the payload to extract the two captioning characters. The caller must check outGotClock to de...
Definition: ancillarydata_cea608_line21.cpp:351
CC_LEVEL_TRANS
const uint8_t CC_LEVEL_TRANS
Definition: ancillarydata_cea608_line21.cpp:183
AJA_SUCCESS
#define AJA_SUCCESS(_status_)
Definition: types.h:370
TRANSITION_PRE
const uint32_t TRANSITION_PRE
Definition: ancillarydata_cea608_line21.cpp:198
AJAAncillaryData::m_rcvDataValid
bool m_rcvDataValid
This is set true (or not) by ParsePayloadData()
Definition: ancillarydata.h:1158
CC_DEFAULT_ENCODE_OFFSET
const uint32_t CC_DEFAULT_ENCODE_OFFSET
Definition: ancillarydata_cea608_line21.cpp:106
AJAAncillaryData::m_SID
uint8_t m_SID
Official SMPTE secondary ID (or DBN - w/o parity)
Definition: ancillarydata.h:1153
AJAAncillaryData::SetLocationLineNumber
virtual AJAStatus SetLocationLineNumber(const uint16_t inLineNum)
Sets my ancillary data "location" frame line number.
Definition: ancillarydata.cpp:321
AJAAncillaryData::m_payload
ByteVector m_payload
My payload data (DC = size)
Definition: ancillarydata.h:1157
AJAAncillaryData_Cea608_Line21::InitEncodeBuffer
virtual AJAStatus InitEncodeBuffer(const uint32_t inLineStartOffset, uint32_t &outDataStartOffset)
Initializes the payload buffer with all of the "static" pixels, e.g. run-in clock,...
Definition: ancillarydata_cea608_line21.cpp:205
std
Definition: json.hpp:5362
AJAAncillaryData_Cea608_Line21::EncodeCharacter
virtual uint8_t * EncodeCharacter(uint8_t *ptr, const uint8_t inChar)
Encodes a single 8-bit character from just after the transition to the first bit until just before th...
Definition: ancillarydata_cea608_line21.cpp:289
CC_LEVEL_MID
const uint8_t CC_LEVEL_MID
Definition: ancillarydata_cea608_line21.cpp:182
AJAAncillaryData_Cea608::m_char1
uint8_t m_char1
Definition: ancillarydata_cea608.h:118
AJAAncillaryData_Cea608_Line21::operator=
virtual AJAAncillaryData_Cea608_Line21 & operator=(const AJAAncillaryData_Cea608_Line21 &inRHS)
Assignment operator – replaces my contents with the right-hand-side value.
Definition: ancillarydata_cea608_line21.cpp:62
AJAAncillaryData_Cea608::m_char2
uint8_t m_char2
Definition: ancillarydata_cea608.h:119
AJAAncillaryData::m_ancType
AJAAncDataType m_ancType
One of a known set of ancillary data types (or "Custom" if not identified)
Definition: ancillarydata.h:1159
AJAAncillaryData_Cea608_Line21::GeneratePayloadData
virtual AJAStatus GeneratePayloadData(void)
Generate the payload data from the "local" ancillary data.
Definition: ancillarydata_cea608_line21.cpp:108
xHEX0N
#define xHEX0N(__x__, __n__)
Definition: ntv2publicinterface.h:5604
AJAAncDataType_Cea608_Line21
@ AJAAncDataType_Cea608_Line21
CEA608 SD Closed Captioning ("Line 21" waveform)
Definition: ancillarydata.h:52
AJAAncillaryData_Cea608_Line21_DID
const uint8_t AJAAncillaryData_Cea608_Line21_DID
Definition: ancillarydata_cea608_line21.h:17
AJAAncillaryData_Cea608_Line21::Init
void Init(void)
Definition: ancillarydata_cea608_line21.cpp:49
TRANSITION_WIDTH
const uint32_t TRANSITION_WIDTH
Definition: ancillarydata_cea608_line21.cpp:200
AJAAncillaryData_Cea608::operator=
AJAAncillaryData_Cea608 & operator=(const AJAAncillaryData_Cea608 &inRHS)
Assignment operator – replaces my contents with the right-hand-side value.
Definition: ancillarydata_cea608.cpp:57