AJA NTV2 SDK  17.5.0.1242
NTV2 SDK 17.5.0.1242
ancillarydata_timecode.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
9 #include <iomanip>
10 
11 
12 using namespace std;
13 
14 
16  : AJAAncillaryData ()
17 {
18  Init();
19 }
20 
21 
23  : AJAAncillaryData ()
24 {
25  Init();
26  *this = clone;
27 }
28 
29 
31  : AJAAncillaryData ()
32 {
33  Init();
34  if (pClone)
35  *this = *pClone;
36 }
37 
38 
40  : AJAAncillaryData (pData)
41 {
42  Init();
43 }
44 
45 
47 {
48  uint8_t i;
49 
50  for (i = 0; i < kNumTimeDigits; i++)
51  m_timeDigits[i] = 0;
52 
53  for (i = 0; i < kNumBinaryGroups; i++)
54  m_binaryGroup[i] = 0;
55 }
56 
57 
59 {
60  if (this != &inRHS) // ignore self-assignment
61  {
62  AJAAncillaryData::operator = (inRHS); // copy the base class stuff
63 
64  // copy the local stuff
65  uint8_t i;
66  for (i = 0; i < kNumTimeDigits; i++)
67  m_timeDigits[i] = inRHS.m_timeDigits[i];
68 
69  for (i = 0; i < kNumBinaryGroups; i++)
70  m_binaryGroup[i] = inRHS.m_binaryGroup[i];
71  }
72  return *this;
73 }
74 
75 
77 {
79  Init();
80 }
81 
82 
84 {
85  // Since I have no "concrete" transport of my own, this must be done by my derived classes.
86  m_rcvDataValid = false;
87  return AJA_STATUS_SUCCESS;
88 }
89 
90 
92 {
93  (void) pAncData;
94  // Since I have no "concrete" transport of my own, this must be done by my derived classes.
96 }
97 
98 
99 //----------------------
100 
101 // sets "raw" hex value, with no attempt to second-guess what the value is used for
102 // Note: "digitNum" is in transmission order, i.e. 0 = ls value, 7 = ms value)
103 AJAStatus AJAAncillaryData_Timecode::SetTimeHexValue (const uint8_t inDigitNum, const uint8_t inHexValue, const uint8_t inMask)
104 {
105  if (inDigitNum >= kNumTimeDigits)
106  return AJA_STATUS_RANGE;
107 
108  m_timeDigits[inDigitNum] = (m_timeDigits[inDigitNum] & ~inMask) | (inHexValue & inMask);
109  return AJA_STATUS_SUCCESS;
110 }
111 
112 
113 // gets "raw" hex value, with no attempt to second-guess what the value is used for
114 // Note: "digitNum" is in transmission order, i.e. 0 = ls value, 7 = ms value)
115 AJAStatus AJAAncillaryData_Timecode::GetTimeHexValue (uint8_t inDigitNum, uint8_t & outHexValue, uint8_t inMask) const
116 {
117  if (inDigitNum >= kNumTimeDigits)
118  return AJA_STATUS_RANGE;
119 
120  outHexValue = (m_timeDigits[inDigitNum] & inMask);
121  return AJA_STATUS_SUCCESS;
122 }
123 
124 
125 // Sets time digits assuming "time" values. Masks each digit according to the number of bits it actually uses in normal timecode applications.
126 // Note that the parameter order is the REVERSE of that used by SetTimeHexValue(): this order proceeds from ms digit (hour tens) to ls digit (frame units).
127 AJAStatus AJAAncillaryData_Timecode::SetTimeDigits (uint8_t hourTens, uint8_t hourUnits, uint8_t minuteTens, uint8_t minuteUnits, uint8_t secondTens, uint8_t secondUnits, uint8_t frameTens, uint8_t frameUnits)
128 {
129  // Note: each digit is masked to keep only the number of bits allotted to it in the ancillary payload,
130  // however no "time" limit-checking is done at this point, so it is possible to pass in (and get back!)
131  // hex values that are out of BCD range and/or not appropriate for the digit (e.g. "38 hours...").
132  // This allows "clever" users to use the bits for other nefarious purposes, but also allows for "bad"
133  // timecode. In other words, if you (the Caller) care about correct range-checking of time values, do it yourself!
134  SetTimeHexValue(kTcHourTens, hourTens, 0x03); // retain 2 ls bits
135  SetTimeHexValue(kTcHourUnits, hourUnits ); // retain 4 ls bits
136  SetTimeHexValue(kTcMinuteTens, minuteTens, 0x07); // retain 3 ls bits
137  SetTimeHexValue(kTcMinuteUnits, minuteUnits ); // retain 4 ls bits
138  SetTimeHexValue(kTcSecondTens, secondTens, 0x07); // retain 3 ls bits
139  SetTimeHexValue(kTcSecondUnits, secondUnits ); // retain 4 ls bits
140  SetTimeHexValue(kTcFrameTens, frameTens, 0x03); // retain 2 ls bits
141  SetTimeHexValue(kTcFrameUnits, frameUnits ); // retain 4 ls bits
142  return AJA_STATUS_SUCCESS;
143 }
144 
145 
146 // Gets time digits assuming "time" values. Masks each digit according to the number of bits it actually uses in normal timecode applications.
147 // Note that the parameter order is the REVERSE of that used by GetTimeHexValue(): this order proceeds from ms digit (hour tens) to ls digit (frame units).
148 AJAStatus AJAAncillaryData_Timecode::GetTimeDigits (uint8_t& hourTens, uint8_t& hourUnits, uint8_t& minuteTens, uint8_t& minuteUnits, uint8_t& secondTens, uint8_t& secondUnits, uint8_t& frameTens, uint8_t& frameUnits) const
149 {
150  GetTimeHexValue(kTcHourTens, hourTens, 0x03); // retain 2 ls bits
151  GetTimeHexValue(kTcHourUnits, hourUnits ); // retain 4 ls bits
152  GetTimeHexValue(kTcMinuteTens, minuteTens, 0x07); // retain 3 ls bits
153  GetTimeHexValue(kTcMinuteUnits, minuteUnits ); // retain 4 ls bits
154  GetTimeHexValue(kTcSecondTens, secondTens, 0x07); // retain 3 ls bits
155  GetTimeHexValue(kTcSecondUnits, secondUnits ); // retain 4 ls bits
156  GetTimeHexValue(kTcFrameTens, frameTens, 0x03); // retain 2 ls bits
157  GetTimeHexValue(kTcFrameUnits, frameUnits ); // retain 4 ls bits
158  return AJA_STATUS_SUCCESS;
159 }
160 
161 
162 AJAStatus AJAAncillaryData_Timecode::SetTime (AJAAncillaryData_Timecode_Format tcFmt, uint32_t hours, uint32_t minutes, uint32_t seconds, uint32_t frames)
163 {
164  if ( (hours >= 24) || (minutes >= 60) || (seconds >= 60) )
165  return AJA_STATUS_RANGE;
166 
167  uint32_t framesPerSecond = 0;
168  switch (tcFmt)
169  {
170  case AJAAncillaryData_Timecode_Format_60fps: framesPerSecond = 60; break;
171  case AJAAncillaryData_Timecode_Format_50fps: framesPerSecond = 50; break;
172  case AJAAncillaryData_Timecode_Format_48fps: framesPerSecond = 48; break;
173  case AJAAncillaryData_Timecode_Format_30fps: framesPerSecond = 30; break;
174  case AJAAncillaryData_Timecode_Format_25fps: framesPerSecond = 25; break;
175  case AJAAncillaryData_Timecode_Format_24fps: framesPerSecond = 24; break;
176  default: framesPerSecond = 0; break; // triggers "range" error
177  }
178 
179  if (frames >= framesPerSecond)
180  return AJA_STATUS_RANGE;
181 
182 
184  {
185  // for "high" frame rates we need to use the "field ID" bit as an added ls bit to extend the frame digit range
186  bool bOddFrame = (frames % 2 == 1 ? true : false);
187  frames = frames / 2;
188 
189  SetFieldIdFlag(bOddFrame, tcFmt); // note that FieldID does NOT get changed for "low" frame rates!
190  }
191 
192  SetTimeDigits( (uint8_t)(hours / 10), (uint8_t)(hours % 10), // hour digits
193  (uint8_t)(minutes / 10), (uint8_t)(minutes % 10), // minute digits
194  (uint8_t)(seconds / 10), (uint8_t)(seconds % 10), // second digits
195  (uint8_t)(frames / 10), (uint8_t)(frames % 10) ); // frame digits
196 
197  return AJA_STATUS_SUCCESS;
198 }
199 
200 
201 AJAStatus AJAAncillaryData_Timecode::GetTime (AJAAncillaryData_Timecode_Format tcFmt, uint32_t& hours, uint32_t& minutes, uint32_t& seconds, uint32_t& frames) const
202 {
203  uint8_t hourTens, hourUnits, minuteTens, minuteUnits, secondTens, secondUnits, frameTens, frameUnits;
204  GetTimeDigits(hourTens, hourUnits, minuteTens, minuteUnits, secondTens, secondUnits, frameTens, frameUnits);
205 
206  hours = (hourTens * 10) + hourUnits;
207  minutes = (minuteTens * 10) + minuteUnits;
208  seconds = (secondTens * 10) + secondUnits;
209  frames = (frameTens * 10) + frameUnits;
210 
211  // for "high" frame rates we need to include the "field ID" bit as an added ls bit to extend the frame digit range
213  {
214  bool bFieldID = false;
215  GetFieldIdFlag(bFieldID, tcFmt);
216 
217  frames = (frames * 2) + (bFieldID ? 1 : 0);
218  }
219 
220  return AJA_STATUS_SUCCESS;
221 }
222 
223 
224 AJAStatus AJAAncillaryData_Timecode::SetTimecode (const AJATimeCode & inTimecode, const AJATimeBase & inTimeBase, const bool inIsDropFrame)
225 {
226  uint32_t hours, minutes, seconds, frames;
227  inTimecode.QueryHmsf (hours, minutes, seconds, frames, inTimeBase, inIsDropFrame);
229  SetTime (tcFmt, hours, minutes, seconds, frames);
230  SetDropFrameFlag (inIsDropFrame, tcFmt);
231  return AJA_STATUS_SUCCESS;
232 }
233 
234 
236 {
238 
239  uint32_t hours, minutes, seconds, frames;
240  GetTime(tcFmt, hours, minutes, seconds, frames);
241 
242  bool bDropFrame = false;
243  GetDropFrameFlag(bDropFrame, tcFmt);
244 
245  outTimecode.SetHmsf(hours, minutes, seconds, frames, inTimeBase, bDropFrame);
246 
247  return AJA_STATUS_SUCCESS;
248 }
249 
250 
251 //----------------------
252 
253 // sets "raw" hex value, with no attempt to second-guess what the value is used for
254 // Note: "digitNum" is in transmission order, i.e. 0 = ls (BG1) value, 7 = ms (BG8) value)
255 AJAStatus AJAAncillaryData_Timecode::SetBinaryGroupHexValue(uint8_t digitNum, uint8_t hexValue, uint8_t mask)
256 {
257  if (digitNum >= kNumBinaryGroups)
258  return AJA_STATUS_RANGE;
259 
260  m_binaryGroup[digitNum] = (m_binaryGroup[digitNum] & ~mask) | (hexValue & mask);
261  return AJA_STATUS_SUCCESS;
262 }
263 
264 
265 // gets "raw" hex value, with no attempt to second-guess what the value is used for
266 // Note: "digitNum" is in transmission order, i.e. 0 = ls (BG1) value, 7 = ms (BG8) value)
267 AJAStatus AJAAncillaryData_Timecode::GetBinaryGroupHexValue (uint8_t digitNum, uint8_t& hexValue, uint8_t mask) const
268 {
269  if (digitNum >= kNumBinaryGroups)
270  return AJA_STATUS_RANGE;
271 
272  hexValue = (m_binaryGroup[digitNum] & mask);
273  return AJA_STATUS_SUCCESS;
274 }
275 
276 
277 AJAStatus AJAAncillaryData_Timecode::SetBinaryGroups (uint8_t bg8, uint8_t bg7, uint8_t bg6, uint8_t bg5, uint8_t bg4, uint8_t bg3, uint8_t bg2, uint8_t bg1)
278 {
287  return AJA_STATUS_SUCCESS;
288 }
289 
290 
291 AJAStatus AJAAncillaryData_Timecode::GetBinaryGroups (uint8_t& bg8, uint8_t& bg7, uint8_t& bg6, uint8_t& bg5, uint8_t& bg4, uint8_t& bg3, uint8_t& bg2, uint8_t& bg1) const
292 {
301  return AJA_STATUS_SUCCESS;
302 }
303 
304 
306 {
307  // the Field ID flag bit assignment varies depending on the video format
308  switch (tcFmt)
309  {
310  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
312  if (bFlag)
313  m_timeDigits[kTcHourTens] |= 0x08; // bit 3 of Hour Tens digit
314  else
315  m_timeDigits[kTcHourTens] &= 0xF7;
316  break;
317 
318  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
319  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
320  if (bFlag)
321  m_timeDigits[kTcSecondTens] |= 0x08; // bit 3 of Second Tens digit
322  else
323  m_timeDigits[kTcSecondTens] &= 0xF7;
324  break;
325 
326  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
327  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
329  if (bFlag)
330  m_timeDigits[kTcSecondTens] |= 0x08; // bit 3 of Second Tens digit
331  else
332  m_timeDigits[kTcSecondTens] &= 0xF7;
333  break;
334 
335  default:
336  return AJA_STATUS_RANGE;
337  }
338 
339  return AJA_STATUS_SUCCESS;
340 }
341 
342 
344 {
345  // the Field ID flag bit assignment varies depending on the video format
346  switch (tcFmt)
347  {
348  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
350  bFlag = ((m_timeDigits[kTcHourTens] & 0x08) != 0); // bit 3 of Hour Tens digit
351  break;
352 
353  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
354  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
355  bFlag = ((m_timeDigits[kTcSecondTens] & 0x08) != 0); // bit 3 of Second Tens digit
356  break;
357 
358  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
359  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
361  bFlag = ((m_timeDigits[kTcSecondTens] & 0x08) != 0); // bit 3 of Second Tens digit
362  break;
363 
364  default:
365  return AJA_STATUS_RANGE;
366  }
367 
368  return AJA_STATUS_SUCCESS;
369 }
370 
371 
373 {
374  switch (tcFmt)
375  {
376  // note: "Drop Frame" is not a valid flag for 25 fps ("PAL") video and should always be set to 0.
377  // However, we're not going to stand in the way of someone who really wants to set it...
378  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
380  if (bFlag)
381  m_timeDigits[kTcFrameTens] |= 0x04; // bit 2 of Frame Tens digit
382  else
383  m_timeDigits[kTcFrameTens] &= 0xFB;
384  break;
385 
386  // note: "Drop Frame" is not a valid flag for 23.98/24 fps video and should always be set to 0.
387  // However, we're not going to stand in the way of someone who really wants to set it...
388  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
389  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
390  if (bFlag)
391  m_timeDigits[kTcFrameTens] |= 0x04; // bit 2 of Frame Tens digit
392  else
393  m_timeDigits[kTcFrameTens] &= 0xFB;
394  break;
395 
396  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
397  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
399  if (bFlag)
400  m_timeDigits[kTcFrameTens] |= 0x04; // bit 2 of Frame Tens digit
401  else
402  m_timeDigits[kTcFrameTens] &= 0xFB;
403  break;
404 
405  default:
406  return AJA_STATUS_RANGE;
407  }
408 
409  return AJA_STATUS_SUCCESS;
410 }
411 
412 
414 {
415  switch (tcFmt)
416  {
417  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
419  bFlag = ((m_timeDigits[kTcFrameTens] & 0x04) != 0); // bit 2 of Frame Tens digit
420  break;
421 
422  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
423  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
424  bFlag = ((m_timeDigits[kTcFrameTens] & 0x04) != 0); // bit 2 of Frame Tens digit
425  break;
426 
427  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
428  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
430  bFlag = ((m_timeDigits[kTcFrameTens] & 0x04) != 0); // bit 2 of Frame Tens digit
431  break;
432 
433  default:
434  return AJA_STATUS_RANGE;
435  }
436 
437  return AJA_STATUS_SUCCESS;
438 }
439 
440 
442 {
443  switch (tcFmt)
444  {
445  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
447  if (bFlag)
448  m_timeDigits[kTcFrameTens] |= 0x08; // bit 3 of Frame Tens digit
449  else
450  m_timeDigits[kTcFrameTens] &= 0xF7;
451  break;
452 
453  // note: "Color Frame" is not a valid flag for 23.98/24 fps video and should always be set to 0.
454  // However, we're not going to stand in the way of someone who really wants to set it...
455  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
456  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
457  if (bFlag)
458  m_timeDigits[kTcFrameTens] |= 0x08; // bit 3 of Frame Tens digit
459  else
460  m_timeDigits[kTcFrameTens] &= 0xF7;
461  break;
462 
463  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
464  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
466  if (bFlag)
467  m_timeDigits[kTcFrameTens] |= 0x08; // bit 3 of Frame Tens digit
468  else
469  m_timeDigits[kTcFrameTens] &= 0xF7;
470  break;
471 
472  default:
473  return AJA_STATUS_RANGE;
474  }
475 
476  return AJA_STATUS_SUCCESS;
477 }
478 
479 
481 {
482  switch (tcFmt)
483  {
484  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
486  bFlag = ((m_timeDigits[kTcFrameTens] & 0x08) != 0); // bit 3 of Frame Tens digit
487  break;
488 
489  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
490  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
491  bFlag = ((m_timeDigits[kTcFrameTens] & 0x08) != 0); // bit 3 of Frame Tens digit
492  break;
493 
494  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
495  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
497  bFlag = ((m_timeDigits[kTcFrameTens] & 0x08) != 0); // bit 3 of Frame Tens digit
498  break;
499 
500  default:
501  return AJA_STATUS_RANGE;
502  }
503 
504  return AJA_STATUS_SUCCESS;
505 }
506 
507 
509 {
510  // the binary group flag bits vary depending on the video format
511  switch (tcFmt)
512  {
513  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
515 
516  if ((bgFlag & 0x04) != 0) // BG Flag, bit 2:
517  m_timeDigits[kTcMinuteTens] |= 0x08; // bit 3 of Minute Tens digit
518  else
519  m_timeDigits[kTcMinuteTens] &= 0xF7;
520 
521  if ((bgFlag & 0x02) != 0) // BG Flag, bit 1:
522  m_timeDigits[kTcHourTens] |= 0x04; // bit 2 of Hour Tens digit
523  else
524  m_timeDigits[kTcHourTens] &= 0xFB;
525 
526  if ((bgFlag & 0x01) != 0) // BG Flag, bit 0:
527  m_timeDigits[kTcSecondTens] |= 0x08; // bit 3 of Second Tens digit
528  else
529  m_timeDigits[kTcSecondTens] &= 0xF7;
530 
531  break;
532 
533 
534  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
535  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
536 
537  if ((bgFlag & 0x04) != 0) // BG Flag, bit 2:
538  m_timeDigits[kTcHourTens] |= 0x08; // bit 3 of Hour Tens digit
539  else
540  m_timeDigits[kTcHourTens] &= 0xF7;
541 
542  if ((bgFlag & 0x02) != 0) // BG Flag, bit 1:
543  m_timeDigits[kTcHourTens] |= 0x04; // bit 2 of Hour Tens digit
544  else
545  m_timeDigits[kTcHourTens] &= 0xFB;
546 
547  if ((bgFlag & 0x01) != 0) // BG Flag, bit 0:
548  m_timeDigits[kTcMinuteTens] |= 0x08; // bit 3 of Minute Tens digit
549  else
550  m_timeDigits[kTcMinuteTens] &= 0xF7;
551 
552  break;
553 
554  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
555  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
557 
558  if ((bgFlag & 0x04) != 0) // BG Flag, bit 2:
559  m_timeDigits[kTcHourTens] |= 0x08; // bit 3 of Hour Tens digit
560  else
561  m_timeDigits[kTcHourTens] &= 0xF7;
562 
563  if ((bgFlag & 0x02) != 0) // BG Flag, bit 1:
564  m_timeDigits[kTcHourTens] |= 0x04; // bit 2 of Hour Tens digit
565  else
566  m_timeDigits[kTcHourTens] &= 0xFB;
567 
568  if ((bgFlag & 0x01) != 0) // BG Flag, bit 0:
569  m_timeDigits[kTcMinuteTens] |= 0x08; // bit 3 of Minute Tens digit
570  else
571  m_timeDigits[kTcMinuteTens] &= 0xF7;
572 
573  break;
574 
575  default:
576  return AJA_STATUS_RANGE;
577  }
578 
579  return AJA_STATUS_SUCCESS;
580 }
581 
582 
584 {
585  uint8_t bf2, bf1, bf0;
586 
587  // the binary group flag bits vary depending on the video format
588  switch (inFormat)
589  {
590  case AJAAncillaryData_Timecode_Format_25fps: // 25 fps ("PAL") format
592  bf2 = (m_timeDigits[kTcMinuteTens] & 0x08) >> 3; // bit 3 of Hour Tens digit
593  bf1 = (m_timeDigits[kTcHourTens] & 0x04) >> 2; // bit 2 of Hour Tens digit
594  bf0 = (m_timeDigits[kTcSecondTens] & 0x08) >> 3; // bit 3 of Second Tens digit
595  break;
596 
597  case AJAAncillaryData_Timecode_Format_24fps: // 24/23.98 fps format
598  case AJAAncillaryData_Timecode_Format_48fps: // 48/47.95 fps
599  bf2 = (m_timeDigits[kTcHourTens] & 0x08) >> 3; // bit 3 of Hour Tens digit
600  bf1 = (m_timeDigits[kTcHourTens] & 0x04) >> 2; // bit 2 of Hour Tens digit
601  bf0 = (m_timeDigits[kTcMinuteTens] & 0x08) >> 3; // bit 3 of Minute Tens digit
602  break;
603 
604  case AJAAncillaryData_Timecode_Format_30fps: // 30/29.97 fps ("NTSC") format
605  case AJAAncillaryData_Timecode_Format_60fps: // 60/59.94 fps
607  bf2 = (m_timeDigits[kTcHourTens] & 0x08) >> 3; // bit 3 of Hour Tens digit
608  bf1 = (m_timeDigits[kTcHourTens] & 0x04) >> 2; // bit 2 of Hour Tens digit
609  bf0 = (m_timeDigits[kTcMinuteTens] & 0x08) >> 3; // bit 3 of Minute Tens digit
610  break;
611 
612  default:
613  return AJA_STATUS_RANGE;
614  }
615 
616  outBGFlag = (bf2 << 2) + (bf1 << 1) + bf0;
617  return AJA_STATUS_SUCCESS;
618 }
619 
620 
622 {
624 
625  int64_t rate, duration;
626  timeBase.GetFrameRate(rate, duration);
627  double frameRate = (double)rate / (double)duration;
628 
629  // we're just going to coarsely (and arbitrarily) quantize the excruciatingly accurate frame rate...
630  if (frameRate < 24.5)
632  else if (frameRate < 28.0)
634  else if (frameRate < 35.0)
636  else if (frameRate < 49.0)
638  else if (frameRate < 55.0)
640  else
642  return tcFmt;
643 }
644 
645 
646 ostream & AJAAncillaryData_Timecode::Print (ostream & debugStream, const bool bShowDetail) const
647 {
648  debugStream << IDAsString() << "(" << ::AJAAncDataCodingToString (m_coding) << ")" << endl;
649  AJAAncillaryData::Print (debugStream, bShowDetail);
650 
651  uint8_t timeDigits[kNumTimeDigits];
652  bool bFieldIdFlag, bColorFrameFlag, bDropFrameFlag;
653  uint8_t binaryGroup [kNumBinaryGroups];
654  uint8_t binaryGroupFlag;
655 
656  GetTimeDigits (timeDigits[kTcHourTens], timeDigits[kTcHourUnits], timeDigits[kTcMinuteTens], timeDigits[kTcMinuteUnits], timeDigits[kTcSecondTens], timeDigits[kTcSecondUnits], timeDigits[kTcFrameTens], timeDigits[kTcFrameUnits]);
657  GetFieldIdFlag (bFieldIdFlag);
658  GetColorFrameFlag (bColorFrameFlag);
659  GetDropFrameFlag (bDropFrameFlag);
660  GetBinaryGroups (binaryGroup[kBg8], binaryGroup[kBg7], binaryGroup[kBg6], binaryGroup[kBg5], binaryGroup[kBg4], binaryGroup[kBg3], binaryGroup[kBg2], binaryGroup[kBg1]);
661  GetBinaryGroupFlag (binaryGroupFlag);
662 
663  debugStream << endl
664  << "Base Timecode Info:" << endl
665  << "Time: " << dec << setw(1) << (uint32_t)timeDigits[kTcHourTens] << setw(1) << (uint32_t)timeDigits[kTcHourUnits]
666  << ":" << setw(1) << (uint32_t)timeDigits[kTcMinuteTens] << setw(1) << (uint32_t)timeDigits[kTcMinuteUnits]
667  << ":" << setw(1) << (uint32_t)timeDigits[kTcSecondTens] << setw(1) << (uint32_t)timeDigits[kTcSecondUnits]
668  << ":" << setw(1) << (uint32_t)timeDigits[kTcFrameTens] << setw(1) << (uint32_t)timeDigits[kTcFrameUnits] << endl
669  << "Field ID Flag: " << (bFieldIdFlag ? "f1" : "f0") << endl
670  << "Drop Frame Flag: " << (bDropFrameFlag ? "Drop" : "Non-drop") << endl
671  << "Color Frame: " << (bColorFrameFlag ? "On" : "Off") << endl
672  << "Binary Group: " << hex << setw(1) << uint16_t(binaryGroup[kBg8]) << setw(1) << uint16_t(binaryGroup[kBg7])
673  << ":" << setw(1) << uint16_t(binaryGroup[kBg6]) << setw(1) << uint16_t(binaryGroup[kBg5])
674  << ":" << setw(1) << uint16_t(binaryGroup[kBg4]) << setw(1) << uint16_t(binaryGroup[kBg3])
675  << ":" << setw(1) << uint16_t(binaryGroup[kBg2]) << setw(1) << uint16_t(binaryGroup[kBg1]) << endl
676  << "BG Flag: " << uint16_t(binaryGroupFlag);
677  return debugStream;
678 }
679 
681 {
682  ostringstream oss;
683  uint8_t timeDigits[kNumTimeDigits];
684  GetTimeDigits (timeDigits[kTcHourTens], timeDigits[kTcHourUnits], timeDigits[kTcMinuteTens], timeDigits[kTcMinuteUnits], timeDigits[kTcSecondTens], timeDigits[kTcSecondUnits], timeDigits[kTcFrameTens], timeDigits[kTcFrameUnits]);
685  oss << dec << setw(1) << uint32_t(timeDigits[kTcHourTens]) << setw(1) << uint32_t(timeDigits[kTcHourUnits])
686  << ":" << setw(1) << uint32_t(timeDigits[kTcMinuteTens]) << setw(1) << uint32_t(timeDigits[kTcMinuteUnits])
687  << ":" << setw(1) << uint32_t(timeDigits[kTcSecondTens]) << setw(1) << uint32_t(timeDigits[kTcSecondUnits])
688  << ":" << setw(1) << uint32_t(timeDigits[kTcFrameTens]) << setw(1) << uint32_t(timeDigits[kTcFrameUnits]);
689  return oss.str();
690 }
AJAAncillaryData_Timecode::SetBinaryGroupFlag
virtual AJAStatus SetBinaryGroupFlag(const uint8_t inBGFlag, const AJAAncillaryData_Timecode_Format inFormat=AJAAncillaryData_Timecode_Format_Unknown)
Sets my binary group flag (3 bits).
Definition: ancillarydata_timecode.cpp:508
AJAAncillaryData_Timecode::kBg5
@ kBg5
Definition: ancillarydata_timecode.h:290
AJAAncillaryData_Timecode
This is the base class for the AJAAncillaryData_Timecode_ATC and AJAAncillaryData_Timecode_VITC class...
Definition: ancillarydata_timecode.h:36
AJAAncillaryData_Timecode::kTcFrameTens
@ kTcFrameTens
Definition: ancillarydata_timecode.h:272
AJAAncillaryData_Timecode_Format_30fps
@ AJAAncillaryData_Timecode_Format_30fps
Definition: ancillarydata_timecode.h:24
AJAAncillaryData_Timecode::kTcSecondTens
@ kTcSecondTens
Definition: ancillarydata_timecode.h:274
AJAAncillaryData_Timecode::SetColorFrameFlag
virtual AJAStatus SetColorFrameFlag(bool bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown)
Sets my color frame flag.
Definition: ancillarydata_timecode.cpp:441
AJAAncDataType_Unknown
@ AJAAncDataType_Unknown
Includes data that is valid, but we don't recognize.
Definition: ancillarydata.h:46
AJAAncillaryData_Timecode::kBg8
@ kBg8
Definition: ancillarydata_timecode.h:293
AJAAncillaryData_Timecode::SetDropFrameFlag
virtual AJAStatus SetDropFrameFlag(bool bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown)
Sets my drop frame flag.
Definition: ancillarydata_timecode.cpp:372
AJAAncillaryData_Timecode::kNumTimeDigits
@ kNumTimeDigits
Definition: ancillarydata_timecode.h:279
AJATimeBase::GetFrameRate
void GetFrameRate(int64_t &frameTimeScale, int64_t &frameDuration) const
Definition: timebase.cpp:133
AJA_STATUS_SUCCESS
@ AJA_STATUS_SUCCESS
Definition: types.h:381
AJAAncillaryData_Timecode::TimecodeString
virtual std::string TimecodeString(void) const
Definition: ancillarydata_timecode.cpp:680
AJAAncillaryData_Timecode::kBg4
@ kBg4
Definition: ancillarydata_timecode.h:289
AJAAncillaryData_Timecode::SetTimeDigits
virtual AJAStatus SetTimeDigits(const uint8_t inHourTens, const uint8_t inHourOnes, const uint8_t inMinTens, const uint8_t inMinOnes, const uint8_t inSecsTens, const uint8_t inSecsOnes, const uint8_t inFrameTens, const uint8_t inFrameOnes)
Sets my timecode "time" using discrete BCD digits.
Definition: ancillarydata_timecode.cpp:127
AJAAncDataType
AJAAncDataType
Identifies the ancillary data types that are known to this module.
Definition: ancillarydata.h:44
AJAAncillaryData_Timecode::kBg7
@ kBg7
Definition: ancillarydata_timecode.h:292
AJAAncillaryData_Timecode::SetTime
virtual AJAStatus SetTime(const AJAAncillaryData_Timecode_Format inFormat, const uint32_t inHours, const uint32_t inMinutes, const uint32_t inSeconds, const uint32_t inFrames)
Sets my timecode "time" with hours, minutes, seconds, frames (in decimal, not BCD digits).
Definition: ancillarydata_timecode.cpp:162
AJAAncillaryData_Timecode::SetFieldIdFlag
virtual AJAStatus SetFieldIdFlag(bool bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown)
Sets my FieldID flag.
Definition: ancillarydata_timecode.cpp:305
AJAAncillaryData_Timecode::GetTimeDigits
virtual AJAStatus GetTimeDigits(uint8_t &outHourTens, uint8_t &outHourOnes, uint8_t &outMinTens, uint8_t &outMinOnes, uint8_t &outSecsTens, uint8_t &outSecsOnes, uint8_t &outFrameTens, uint8_t &outFrameOnes) const
Answers with my current timecode "time" as discrete BCD digits.
Definition: ancillarydata_timecode.cpp:148
AJAAncillaryData_Timecode::GetTimecodeFormatFromTimeBase
static AJAAncillaryData_Timecode_Format GetTimecodeFormatFromTimeBase(const AJATimeBase &inTimeBase)
Get the timecode format that matches the input timebase.
Definition: ancillarydata_timecode.cpp:621
AJAAncillaryData_Timecode::GetDropFrameFlag
virtual AJAStatus GetDropFrameFlag(bool &bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown) const
Definition: ancillarydata_timecode.cpp:413
nlohmann::json_abiNLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON_v3_11_NLOHMANN_JSON_VERSION_PATCH::detail::void
j template void())
Definition: json.hpp:4893
AJAAncillaryData_Timecode::SetBinaryGroupHexValue
virtual AJAStatus SetBinaryGroupHexValue(uint8_t digitNum, uint8_t hexValue, uint8_t mask=0x0f)
Sets my raw "Binary Group" hex values.
Definition: ancillarydata_timecode.cpp:255
AJAAncillaryData_Timecode::kTcFrameUnits
@ kTcFrameUnits
Definition: ancillarydata_timecode.h:271
AJAAncillaryData_Timecode::GetBinaryGroupHexValue
virtual AJAStatus GetBinaryGroupHexValue(uint8_t digitNum, uint8_t &hexValue, uint8_t mask=0x0f) const
Definition: ancillarydata_timecode.cpp:267
AJAAncillaryData_Timecode::kTcSecondUnits
@ kTcSecondUnits
Definition: ancillarydata_timecode.h:273
AJAAncillaryData_Timecode::GetColorFrameFlag
virtual AJAStatus GetColorFrameFlag(bool &bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown) const
Definition: ancillarydata_timecode.cpp:480
AJAAncillaryData_Timecode::AJAAncillaryData_Timecode
AJAAncillaryData_Timecode()
Definition: ancillarydata_timecode.cpp:15
AJAAncillaryData_Timecode::SetTimeHexValue
virtual AJAStatus SetTimeHexValue(const uint8_t inDigitNum, const uint8_t inHexValue, const uint8_t inMask=0x0f)
Sets my raw "time" hex values.
Definition: ancillarydata_timecode.cpp:103
AJAStatus
AJAStatus
Definition: types.h:378
AJAAncillaryData::Print
virtual std::ostream & Print(std::ostream &inOutStream, const bool inDetailed=false) const
Streams a human-readable representation of me to the given output stream.
Definition: ancillarydata.cpp:1409
AJAAncillaryData_Timecode::kTcMinuteUnits
@ kTcMinuteUnits
Definition: ancillarydata_timecode.h:275
AJATimeBase
Definition: timebase.h:18
AJAAncillaryData_Timecode::Clear
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values.
Definition: ancillarydata_timecode.cpp:76
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_Timecode::SetBinaryGroups
virtual AJAStatus SetBinaryGroups(uint8_t bg8, uint8_t bg7, uint8_t bg6, uint8_t bg5, uint8_t bg4, uint8_t bg3, uint8_t bg2, uint8_t bg1)
Sets my binary group values.
Definition: ancillarydata_timecode.cpp:277
AJAAncillaryData_Timecode::GetBinaryGroupFlag
virtual AJAStatus GetBinaryGroupFlag(uint8_t &outBGFlag, const AJAAncillaryData_Timecode_Format inFormat=AJAAncillaryData_Timecode_Format_Unknown) const
Answers with my current binary group flag (3 bits).
Definition: ancillarydata_timecode.cpp:583
AJAAncillaryData_Timecode_Format_48fps
@ AJAAncillaryData_Timecode_Format_48fps
Definition: ancillarydata_timecode.h:23
AJAAncillaryData::m_coding
AJAAncDataCoding m_coding
Analog or digital data.
Definition: ancillarydata.h:1156
AJAAncillaryData_Timecode::m_binaryGroup
uint8_t m_binaryGroup[kNumBinaryGroups]
Definition: ancillarydata_timecode.h:304
AJATimeCode::SetHmsf
void SetHmsf(uint32_t h, uint32_t m, uint32_t s, uint32_t f, const AJATimeBase &timeBase, bool bDropFrame)
Definition: timecode.cpp:284
AJAAncillaryData_Timecode::GetTimecode
virtual AJAStatus GetTimecode(AJATimeCode &outTimecode, const AJATimeBase &inTimeBase) const
Answers with my timecode "time" as an AJATimeCode.
Definition: ancillarydata_timecode.cpp:235
AJAAncillaryData_Timecode::SetTimecode
virtual AJAStatus SetTimecode(const AJATimeCode &inTimecode, const AJATimeBase &inTimeBase, const bool inIsDropFrame)
Sets my timecode "time" from an AJATimeCode.
Definition: ancillarydata_timecode.cpp:224
AJAAncillaryData_Timecode::Init
void Init(void)
Definition: ancillarydata_timecode.cpp:46
AJAAncillaryData_Timecode_Format_Unknown
@ AJAAncillaryData_Timecode_Format_Unknown
Definition: ancillarydata_timecode.h:19
AJAAncillaryData_Timecode::GetTime
virtual AJAStatus GetTime(const AJAAncillaryData_Timecode_Format inFormat, uint32_t &outHours, uint32_t &outMinutes, uint32_t &outSeconds, uint32_t &outFrames) const
Answers with my current timecode "time" as individual hour, minute, second, and frame components (in ...
Definition: ancillarydata_timecode.cpp:201
AJAAncillaryData_Timecode::operator=
AJAAncillaryData_Timecode & operator=(const AJAAncillaryData_Timecode &inRHS)
Assignment operator – replaces my contents with the right-hand-side value.
Definition: ancillarydata_timecode.cpp:58
AJA_STATUS_RANGE
@ AJA_STATUS_RANGE
Definition: types.h:385
AJAAncillaryData_Timecode::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_timecode.cpp:646
AJAAncillaryData::m_rcvDataValid
bool m_rcvDataValid
This is set true (or not) by ParsePayloadData()
Definition: ancillarydata.h:1158
AJAAncillaryData_Timecode::GetBinaryGroups
virtual AJAStatus GetBinaryGroups(uint8_t &bg8, uint8_t &bg7, uint8_t &bg6, uint8_t &bg5, uint8_t &bg4, uint8_t &bg3, uint8_t &bg2, uint8_t &bg1) const
Definition: ancillarydata_timecode.cpp:291
AJAAncillaryData_Timecode::kBg1
@ kBg1
Definition: ancillarydata_timecode.h:286
ancillarydata_timecode.h
Declares the AJAAncillaryData_Timecode class.
AJAAncillaryData::IDAsString
virtual std::string IDAsString(void) const
Definition: ancillarydata.cpp:1428
AJAAncillaryData_Timecode::GetTimeHexValue
virtual AJAStatus GetTimeHexValue(uint8_t inDigitNum, uint8_t &outHexValue, uint8_t inMask=0x0f) const
Answers with my current raw "time" hex values.
Definition: ancillarydata_timecode.cpp:115
AJATimeCode::QueryHmsf
void QueryHmsf(uint32_t &h, uint32_t &m, uint32_t &s, uint32_t &f, const AJATimeBase &timeBase, bool bDropFrame) const
Definition: timecode.cpp:109
AJAAncillaryData_Timecode::RecognizeThisAncillaryData
static AJAAncDataType RecognizeThisAncillaryData(const AJAAncillaryData *pInAncData)
Definition: ancillarydata_timecode.cpp:91
AJAAncillaryData::Clear
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values.
Definition: ancillarydata.cpp:159
AJAAncillaryData_Timecode::kTcHourUnits
@ kTcHourUnits
Definition: ancillarydata_timecode.h:277
AJAAncillaryData::operator=
AJAAncillaryData & operator=(const AJAAncillaryData &inRHS)
Definition: ancillarydata.cpp:1576
std
Definition: json.hpp:5362
AJAAncillaryData_Timecode_Format
AJAAncillaryData_Timecode_Format
Definition: ancillarydata_timecode.h:17
AJAAncDataCodingToString
const std::string & AJAAncDataCodingToString(const AJAAncDataCoding inValue, const bool inCompact=true)
Definition: ancillarydata.cpp:1372
AJAAncillaryData_Timecode::GetFieldIdFlag
virtual AJAStatus GetFieldIdFlag(bool &bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown) const
Definition: ancillarydata_timecode.cpp:343
AJAAncillaryData_Timecode_Format_50fps
@ AJAAncillaryData_Timecode_Format_50fps
Definition: ancillarydata_timecode.h:22
true
#define true
Definition: ntv2devicefeatures.h:26
AJAAncillaryData_Timecode::m_timeDigits
uint8_t m_timeDigits[kNumTimeDigits]
Definition: ancillarydata_timecode.h:303
AJAAncillaryData_Timecode::kTcHourTens
@ kTcHourTens
Definition: ancillarydata_timecode.h:278
AJAAncillaryData_Timecode::ParsePayloadData
virtual AJAStatus ParsePayloadData(void)
Parses out (interprets) the "local" ancillary data from my payload data.
Definition: ancillarydata_timecode.cpp:83
AJAAncillaryData_Timecode::kTcMinuteTens
@ kTcMinuteTens
Definition: ancillarydata_timecode.h:276
AJAAncillaryData_Timecode::kNumBinaryGroups
@ kNumBinaryGroups
Definition: ancillarydata_timecode.h:294
AJAAncillaryData_Timecode_Format_24fps
@ AJAAncillaryData_Timecode_Format_24fps
Definition: ancillarydata_timecode.h:26
AJAAncillaryData_Timecode::kBg6
@ kBg6
Definition: ancillarydata_timecode.h:291
AJAAncillaryData_Timecode::kBg3
@ kBg3
Definition: ancillarydata_timecode.h:288
AJAAncillaryData_Timecode_Format_25fps
@ AJAAncillaryData_Timecode_Format_25fps
Definition: ancillarydata_timecode.h:25
AJAAncillaryData_Timecode_Format_60fps
@ AJAAncillaryData_Timecode_Format_60fps
Definition: ancillarydata_timecode.h:21
AJAAncillaryData_Timecode::kBg2
@ kBg2
Definition: ancillarydata_timecode.h:287
AJATimeCode
Utility class for timecodes.
Definition: timecode.h:17