AJA NTV2 SDK  18.0.0.2122
NTV2 SDK 18.0.0.2122
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 & operator=(const AJAAncillaryData &inRHS)
virtual AJAStatus SetFieldIdFlag(bool bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown)
Sets my FieldID flag.
virtual AJAStatus GetBinaryGroupHexValue(uint8_t digitNum, uint8_t &hexValue, uint8_t mask=0x0f) const
AJAStatus
Definition: types.h:380
AJAAncDataType
Identifies the ancillary data types that are known to this module.
Definition: ancillarydata.h:44
virtual AJAStatus SetDropFrameFlag(bool bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown)
Sets my drop frame flag.
Definition: json.hpp:5362
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values. ...
AJAAncillaryData_Timecode & operator=(const AJAAncillaryData_Timecode &inRHS)
Assignment operator – replaces my contents with the right-hand-side value.
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.
AJAAncDataCoding m_coding
Analog or digital data.
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.
virtual std::ostream & Print(std::ostream &inOutStream, const bool inDetailed=false) const
Streams a human-readable representation of me to the given output stream.
static AJAAncillaryData_Timecode_Format GetTimecodeFormatFromTimeBase(const AJATimeBase &inTimeBase)
Get the timecode format that matches the input timebase.
#define true
Includes data that is valid, but we don&#39;t recognize.
Definition: ancillarydata.h:46
virtual AJAStatus GetTimeHexValue(uint8_t inDigitNum, uint8_t &outHexValue, uint8_t inMask=0x0f) const
Answers with my current raw "time" hex values.
void GetFrameRate(int64_t &frameTimeScale, int64_t &frameDuration) const
Definition: timebase.cpp:133
Utility class for timecodes.
Definition: timecode.h:28
void SetHmsf(uint32_t h, uint32_t m, uint32_t s, uint32_t f, const AJATimeBase &timeBase, bool bDropFrame, bool bStdTcForHfr, uint32_t addFrame)
Definition: timecode.cpp:425
static AJAAncDataType RecognizeThisAncillaryData(const AJAAncillaryData *pInAncData)
for(int i=0;i< g_cTemplates;i++)
Definition: dllentry.cpp:202
void QueryHmsf(uint32_t &h, uint32_t &m, uint32_t &s, uint32_t &f, const AJATimeBase &timeBase, bool bDropFrame) const
Definition: timecode.cpp:292
virtual AJAStatus GetColorFrameFlag(bool &bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown) const
virtual AJAStatus SetBinaryGroupFlag(const uint8_t inBGFlag, const AJAAncillaryData_Timecode_Format inFormat=AJAAncillaryData_Timecode_Format_Unknown)
Sets my binary group flag (3 bits).
Declares the AJAAncillaryData_Timecode class.
virtual AJAStatus SetColorFrameFlag(bool bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown)
Sets my color frame flag.
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).
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)...
This is the base class for the AJAAncillaryData_Timecode_ATC and AJAAncillaryData_Timecode_VITC class...
virtual AJAStatus ParsePayloadData(void)
Parses out (interprets) the "local" ancillary data from my payload data.
virtual AJAStatus SetTimecode(const AJATimeCode &inTimecode, const AJATimeBase &inTimeBase, const bool inIsDropFrame)
Sets my timecode "time" from an AJATimeCode.
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.
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 ...
virtual void Clear(void)
Frees my allocated memory, if any, and resets my members to their default values. ...
virtual AJAStatus GetFieldIdFlag(bool &bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown) const
virtual AJAStatus GetTimecode(AJATimeCode &outTimecode, const AJATimeBase &inTimeBase) const
Answers with my timecode "time" as an AJATimeCode.
const std::string & AJAAncDataCodingToString(const AJAAncDataCoding inValue, const bool inCompact=true)
virtual std::string IDAsString(void) const
I am the principal class that stores a single SMPTE-291 SDI ancillary data packet OR the digitized co...
bool m_rcvDataValid
This is set true (or not) by ParsePayloadData()
uint8_t m_binaryGroup[kNumBinaryGroups]
virtual AJAStatus GetDropFrameFlag(bool &bFlag, AJAAncillaryData_Timecode_Format tcFmt=AJAAncillaryData_Timecode_Format_Unknown) const
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
AJAAncillaryData_Timecode_Format
virtual std::string TimecodeString(void) const
virtual AJAStatus SetTimeHexValue(const uint8_t inDigitNum, const uint8_t inHexValue, const uint8_t inMask=0x0f)
Sets my raw "time" hex values.
uint8_t m_timeDigits[kNumTimeDigits]
virtual std::ostream & Print(std::ostream &inOutStream, const bool inDetailed=false) const
Streams a human-readable representation of me to the given output stream.
virtual AJAStatus SetBinaryGroupHexValue(uint8_t digitNum, uint8_t hexValue, uint8_t mask=0x0f)
Sets my raw "Binary Group" hex values.