AJA NTV2 SDK  17.1.1.1245
NTV2 SDK 17.1.1.1245
ntv2rp188.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: MIT */
8 #include "ntv2rp188.h"
9 #include "stdio.h" // for sprintf
10 
11 using namespace std;
12 
13 
14 //--------------------------------------------------------------------------------------------------------------------
15 // CRP188 definition
16 //--------------------------------------------------------------------------------------------------------------------
17 #if defined (MSWindows)
18 #pragma warning(disable: 4800)
19 #endif
20 
21 const int kDigColon = 10; // index of ':' character
22 const int kDigSemicolon = 11; // index of ';' character
23 const int kDigDash = 12; // index of '-' character
24 const int kDigSpace = 13; // index of ' ' character
25 const int kDigAsterisk = 14; // index of '*' character
26 const int kMaxTCChars = 15; // number of characters we know how to make
27 
28 const int kNumBurnInChars = 11; // number of characters in burn-in display (assume "xx:xx:xx:xx")
29 
30 const int kDigitDotWidth = 24; // width of dot map for each character (NOTE: kDigitDotWidth must be evenly divisible by 6 if you want this to work for 10-bit YUV!)
31 const int kDigitDotHeight = 18; // height of dot map for each character
32 
33 // Timecode "Font" Glyphs for burn-in:
35 {
36 // '0'
37  {
38  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
39  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
40  {0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0},
41  {0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
42  {0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0},
43  {0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0},
44  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
45  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
46  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
47  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
48  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
49  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
50  {0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0},
51  {0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0},
52  {0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
53  {0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0},
54  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
55  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
56  },
57 
58 // '1'
59  {
60  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
61  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
62  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
63  {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
64  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
65  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
66  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
67  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
68  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
69  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
70  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
71  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
72  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
73  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
74  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0},
75  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0},
76  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
77  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
78  },
79 
80 // '2'
81  {
82  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
83  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
84  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0},
85  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
86  {0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0},
87  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
88  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
89  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0},
90  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0},
91  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
92  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0},
93  {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
94  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
95  {0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
96  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
97  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
98  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
99  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
100  },
101 
102 // '3'
103  {
104  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
105  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
106  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
107  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
108  {0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0},
109  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
110  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
111  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0},
112  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
113  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
114  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0},
115  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
116  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
117  {0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0},
118  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
119  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
120  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
121  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
122  },
123 
124 // '4'
125  {
126  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
127  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
128  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
129  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
130  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
131  {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
132  {0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
133  {0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
134  {0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
135  {0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
136  {0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
137  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
138  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
139  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
140  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
141  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0},
142  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
143  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
144  },
145 
146 // '5'
147  {
148  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
149  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
150  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
151  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
152  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
153  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
154  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
155  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0},
156  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
157  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
158  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
159  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
160  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
161  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
162  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
163  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
164  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
165  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
166  },
167 
168 // '6'
169  {
170  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
171  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
172  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
173  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
174  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
175  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
176  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
177  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
178  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
179  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
180  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
181  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
182  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
183  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
184  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
185  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
186  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
187  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
188  },
189 
190 // '7'
191  {
192  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
193  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
194  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
195  {0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
196  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
197  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0},
198  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0},
199  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0},
200  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
201  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0},
202  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0},
203  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
204  {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
205  {0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
206  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
207  {0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
208  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
209  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
210  },
211 
212 // '8'
213  {
214  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
215  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
216  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
217  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
218  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
219  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
220  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
221  {0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0},
222  {0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
223  {0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
224  {0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0},
225  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
226  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
227  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
228  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
229  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
230  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
231  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
232  },
233 
234 // '9'
235  {
236  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
237  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
238  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
239  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
240  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
241  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
242  {0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
243  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
244  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
245  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0},
246  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
247  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
248  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0},
249  {0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0},
250  {0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0},
251  {0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
252  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
253  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
254  },
255 
256 // ':' (colon)
257  {
258  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
259  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
260  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
261  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
262  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
263  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
264  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
265  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
266  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
267  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
268  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
269  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
270  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
271  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
272  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
273  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
274  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
275  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
276  },
277 
278 // ';' (semicolon)
279  {
280  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
281  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
282  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
283  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
284  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
285  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
286  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
287  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
288  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
289  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
290  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
291  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
292  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
293  {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
294  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
295  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
296  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
297  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
298  },
299 
300 // '-' (dash)
301  {
302  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
303  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
304  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
305  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
306  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
307  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
308  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
309  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
310  {0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
311  {0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
312  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
313  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
314  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
315  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
316  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
317  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
318  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
319  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
320  },
321 
322 // ' ' (blank)
323  {
324  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
325  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
326  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
327  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
328  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
329  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
330  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
331  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
332  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
333  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
334  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
335  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
336  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
337  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
338  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
339  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
340  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
341  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
342  },
343 
344 // '*' (asterisk)
345  {
346  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
347  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
348  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
349  {0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0},
350  {0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 3, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
351  {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0},
352  {0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
353  {0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0},
354  {0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 3, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0},
355  {0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 3, 2, 3, 2, 3, 3, 2, 1, 0, 0, 0, 0, 0, 0},
356  {0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 2, 3, 2, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0},
357  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
358  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
359  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
360  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
361  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
362  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
363  {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
364  },
365 };
366 
367 static char bcd[] = {'0','1','2','3','4','5','6','7','8','9','0','0','0','0','0','0'};
368 static char hexChar[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
369 
370 //--------------------------------------------------------------------------------------------------------------------
371 // Constructors
372 //--------------------------------------------------------------------------------------------------------------------
373 
375 {
376  Init();
377  _bInitialized = false;
378 }
379 
380 CRP188::CRP188 (ULWord ulFrms, ULWord ulSecs, ULWord ulMins, ULWord ulHrs, const TimecodeFormat tcFormat)
381 {
382  Init();
383  SetRP188 (ulFrms, ulSecs, ulMins, ulHrs, tcFormat);
384 }
385 
386 CRP188::CRP188 (const RP188_STRUCT & rp188, const TimecodeFormat tcFormat)
387 {
388  Init();
389  SetRP188 (rp188, tcFormat);
390 }
391 
392 CRP188::CRP188 (const NTV2_RP188 & inRP188, const TimecodeFormat tcFormat)
393 {
394  Init ();
395  SetRP188 (inRP188, tcFormat);
396 }
397 
398 CRP188::CRP188 (const string & sRP188, const TimecodeFormat tcFormat)
399 {
400  Init();
401  SetRP188(sRP188, tcFormat);
402 }
403 
404 CRP188::CRP188 (ULWord frames, const TimecodeFormat tcFormat)
405 {
406  Init();
407  SetRP188 (frames, tcFormat);
408 }
409 
410 
412 {
413  if (_pCharRenderMap != NULL)
414  free(_pCharRenderMap);
415 }
416 
417 
419 {
420  _pCharRenderMap = NULL;
421  _bRendered = false;
422  _bInitialized = false;
423  _bFresh = false;
424  _tcFormat = kTCFormatUnknown;
425 }
426 
427 
428 bool CRP188::operator==( const CRP188& s)
429 {
430  bool bResult = true;
431 
432  // this can be fancier: we're just looking for identical hrs/mins/sec/frames
433  // (but NOT checking user bits, field IDs, etc.)
434  ULWord sVal[4];
435 
436  bResult &= s.GetRP188Frms(sVal[0]);
437  bResult &= s.GetRP188Secs(sVal[1]);
438  bResult &= s.GetRP188Mins(sVal[2]);
439  bResult &= s.GetRP188Hrs (sVal[3]);
440 
441  if (bResult)
442  {
443  if ( (_ulVal[0] == sVal[0]) && (_ulVal[1] == sVal[1]) && (_ulVal[2] == sVal[2]) && (_ulVal[3] == sVal[3]) )
444  bResult = true;
445  else
446  bResult = false;
447  }
448 
449  return bResult;
450 }
451 
452 
453 //--------------------------------------------------------------------------------------------------------------------
454 // Setters
455 //--------------------------------------------------------------------------------------------------------------------
456 void CRP188::SetRP188 (const RP188_STRUCT & rp188, const TimecodeFormat tcFormat)
457 {
458  char unitFrames;
459  char tensFrames;
460  char unitSeconds;
461  char tensSeconds;
462  char unitMinutes;
463  char tensMinutes;
464  char unitHours;
465  char tensHours;
466 
467  if (tcFormat != kTCFormatUnknown)
468  _tcFormat = tcFormat;
469 
470  if (rp188.DBB == 0xffffffff)
471  return;
472 
473  ULWord TC0_31 = rp188.Low;
474  ULWord TC32_63 = rp188.High;
475  _bDropFrameFlag = (TC0_31 >> 10) & 0x01; // Drop Frame: timecode bit 10
476 
477  if ( FormatIs60_50fps(_tcFormat) )
478  {
479  // for frame rates > 39 fps, the field ID correlates frame pairs
480  bool bFieldID = (FormatIsPAL(_tcFormat) ? ((TC32_63 & BIT_27) != 0) : ((TC0_31 & BIT_27) != 0) ); // Note: FID is in different words for PAL & NTSC!
481  int numFrames = (((((TC0_31>>8)&0x3) * 10) + (TC0_31&0xF)) * 2) + (int)bFieldID; // double the regular frame count and add fieldID
482  unitFrames = bcd[numFrames % 10];
483  tensFrames = bcd[numFrames / 10];
484  }
485  else
486  {
487  unitFrames = bcd[(TC0_31 )&0xF];
488  tensFrames = bcd[(TC0_31>>8)&0x3];
489  }
490  unitSeconds = bcd[(TC0_31>>16)&0xF];
491  tensSeconds = bcd[(TC0_31>>24)&0x7];
492 
493  unitMinutes = bcd[(TC32_63 )&0xF];
494  tensMinutes = bcd[(TC32_63>> 8)&0x7];
495  unitHours = bcd[(TC32_63>>16)&0xF];
496  tensHours = bcd[(TC32_63>>24)&0x3];
497 
498  _ulVal[0] = (unitFrames-0x30)+((tensFrames-0x30)*10);
499  _ulVal[1] = (unitSeconds-0x30)+((tensSeconds-0x30)*10);
500  _ulVal[2] = (unitMinutes-0x30)+((tensMinutes-0x30)*10);
501  _ulVal[3] = (unitHours-0x30)+((tensHours-0x30)*10);
502 
503  char timecodeString[12];
504  timecodeString[0] = tensHours;
505  timecodeString[1] = unitHours;
506  timecodeString[2] = ':';
507  timecodeString[3] = tensMinutes;
508  timecodeString[4] = unitMinutes;
509  timecodeString[5] = ':';
510  timecodeString[6] = tensSeconds;
511  timecodeString[7] = unitSeconds;
512  if (_bDropFrameFlag)
513  {
514  timecodeString[8] = ';';
515  }
516  else
517  {
518  timecodeString[8] = ':';
519  }
520  timecodeString[9] = tensFrames;
521  timecodeString[10] = unitFrames;
522  timecodeString[11] = '\0';
523 
524  _sHMSF = timecodeString;
525 
526  ConvertTcStrToVal();
527 
528 
529  _rp188 = rp188;
530  _bInitialized = true;
531  _bFresh = ((rp188.DBB & NEW_SELECT_RP188_RCVD) || (rp188.DBB & BIT(18)) || (rp188.DBB & BIT(19)));
532 
533  // User bits
534 
535  _bVaricamActiveF0 = (TC0_31 >> 5) & 0x01; // Varicam "Active Frame 1": timecode bit 5
536  _bVaricamActiveF1 = (TC0_31 >> 4) & 0x01; // Varicam "Active Frame 2": timecode bit 4
537 
538  _bDropFrameFlag = (TC0_31 >> 10) & 0x01; // Drop Frame: timecode bit 10
539  _bColorFrameFlag = (TC0_31 >> 11) & 0x01; // Color Frame: timecode bit 11
540 
541  _varicamRate = (_ulUserBits[3] * 10) + _ulUserBits[2];
542 
543  if ( FormatIsPAL(_tcFormat) )
544  {
545  _fieldID = (TC32_63 >> 27) & 0x01; // Field ID: timecode bit 59 (25 fps spec)
546  }
547  else
548  {
549  _fieldID = (TC0_31 >> 27) & 0x01; // Field ID: timecode bit 27 (30 fps spec)
550  }
551 }
552 
553 
554 void CRP188::SetRP188 (const NTV2_RP188 & inRP188, const TimecodeFormat inFormat)
555 {
556  RP188_STRUCT tmpRP188 (inRP188);
557  SetRP188 (tmpRP188, inFormat);
558 }
559 
560 
561 void CRP188::SetRP188 (const string &sRP188, const TimecodeFormat tcFormat)
562 {
563  if (tcFormat != kTCFormatUnknown)
564  _tcFormat = tcFormat;
565 
566 
567  _sHMSF = sRP188;
568  ConvertTcStrToVal();
569 
570  SetRP188(_ulVal[0], _ulVal[1], _ulVal[2], _ulVal[3], _tcFormat);
571 }
572 
573 
574 void CRP188::SetRP188 (ULWord frames, const TimecodeFormat tcFormat)
575 {
576  if (tcFormat != kTCFormatUnknown)
577  _tcFormat = tcFormat;
578 
579  ULWord ulHrs, ulMins, ulSecs, ulFrms;
580 
581  ConvertFrameCount(frames, _tcFormat, ulHrs, ulMins, ulSecs, ulFrms);
582 
583  SetRP188(ulFrms, ulSecs, ulMins, ulHrs, _tcFormat);
584 }
585 
586 
587 void CRP188::SetRP188 (ULWord ulFrms, ULWord ulSecs, ULWord ulMins, ULWord ulHrs,
588  NTV2FrameRate frameRate, const bool bDropFrame, const bool bSMPTE372)
589 {
590  TimecodeFormat tcFormat = kTCFormat30fpsDF;
591 
592  switch (frameRate)
593  {
594  case NTV2_FRAMERATE_6000: tcFormat = kTCFormat60fps; break;
595  case NTV2_FRAMERATE_5994: tcFormat = kTCFormat60fps; break;
596  case NTV2_FRAMERATE_5000: tcFormat = kTCFormat50fps; break;
597  case NTV2_FRAMERATE_4800: tcFormat = kTCFormat48fps; break;
598  case NTV2_FRAMERATE_3000: tcFormat = kTCFormat30fps; break;
599  case NTV2_FRAMERATE_2997: tcFormat = kTCFormat30fps; break;
600  case NTV2_FRAMERATE_2500: tcFormat = kTCFormat25fps; break;
601  case NTV2_FRAMERATE_2400: tcFormat = kTCFormat24fps; break;
602  case NTV2_FRAMERATE_2398: tcFormat = kTCFormat24fps; break;
603  default: break;
604  }
605 
606  if(frameRate == NTV2_FRAMERATE_2400 && bSMPTE372)
607  tcFormat = kTCFormat48fps;
608 
609  if(frameRate == NTV2_FRAMERATE_3000 && bSMPTE372)
610  tcFormat = kTCFormat60fps;
611 
612  if(frameRate == NTV2_FRAMERATE_2997 && bSMPTE372)
613  tcFormat = kTCFormat60fps;
614 
615  if(frameRate == NTV2_FRAMERATE_2500 && bSMPTE372)
616  tcFormat = kTCFormat50fps;
617 
618  if (tcFormat == kTCFormat30fps && bDropFrame)
619  tcFormat = kTCFormat30fpsDF;
620 
621  if (tcFormat == kTCFormat60fps && bDropFrame)
622  tcFormat = kTCFormat60fpsDF;
623 
624  SetRP188(ulFrms, ulSecs, ulMins, ulHrs, tcFormat);
625 }
626 
627 
628 void CRP188::SetRP188 (ULWord ulFrms, ULWord ulSecs, ULWord ulMins, ULWord ulHrs, const TimecodeFormat tcFormat)
629 {
630  //printf("SetRP188 ulFrms = %d, ulSecs = %d, ulMins = %d, ulHrs = %d, framesPerSecond = %d, bDropFrame = %d, b50Hz = %d\n",
631  // ulFrms, ulSecs, ulMins, ulHrs, framesPerSecond, bDropFrame, b50Hz);
632 
633  if (tcFormat != kTCFormatUnknown)
634  _tcFormat = tcFormat;
635 
636  bool bDropFrame = FormatIsDropFrame(_tcFormat);
637 
638  ULWord framesPerSecond = FramesPerSecond(_tcFormat);
639 
640  // insure that TC elements are valid
641  if (ulFrms >= framesPerSecond)
642  {
643  ulSecs += ulFrms / framesPerSecond;
644  ulFrms %= framesPerSecond;
645  }
646 
647  if (ulSecs > 59)
648  {
649  ulMins += ulSecs / 60;
650  ulSecs %= 60;
651  }
652 
653  if (ulMins > 59)
654  {
655  ulHrs += ulMins / 60;
656  ulMins %= 60;
657  }
658 
659  if (ulHrs >= 24)
660  ulHrs %= 24;
661 
662  // error check: if this is a DropFrame mode, chop off any frames that should have been dropped
663  if (bDropFrame)
664  {
665  if (_tcFormat == kTCFormat30fpsDF)
666  {
667  // there shouldn't be any frames that look like "XX:XX:00:00" or "XX:XX:00:01" unless
668  // we're on an exact 10 minute multiple
669  if ( (ulSecs == 0) && ((ulFrms == 0) || (ulFrms == 1)) )
670  {
671  if ((ulMins % 10) != 0) // not on a "10s" minute? (00, 10, 20, ...)
672  {
673  // bad frame digit - round up to "02"
674  ulFrms = 2;
675  }
676  }
677  }
678  else if (_tcFormat == kTCFormat60fpsDF)
679  {
680  // As far as I know there is no "standard" for 60 fps DropFrame timecode, so we don't really
681  // know which frame(s) to drop. In the mean time, we're going to simply assume that 60 fps
682  // timecode is just like 30 fps timecode with "field" (or half-frame) precision...?
683 
684  // there shouldn't be any frames that look like "XX:XX:00:00" or "XX:XX:00:01" or
685  // "XX:XX:00:02" or "XX:XX:00:03" unless we're on an exact 10 minute multiple
686  if ( (ulSecs == 0) && ((ulFrms == 0) || (ulFrms == 1) || (ulFrms == 2) || (ulFrms == 3)) )
687  {
688  if ((ulMins % 10) != 0) // not on a "10s" minute? (00, 10, 20, ...)
689  {
690  // bad frame digit - round up to "04"
691  ulFrms = 4;
692  }
693  }
694  }
695  }
696 
697  _ulVal[0] = ulFrms;
698  _ulVal[1] = ulSecs;
699  _ulVal[2] = ulMins;
700  _ulVal[3] = ulHrs;
701 
702  // format TC
703  char timeCodeString[80];
704  if (bDropFrame)
705  sprintf(timeCodeString,"%02d:%02d:%02d;%02d", ulHrs, ulMins, ulSecs, ulFrms); // drop frame uses ';'
706  else
707  sprintf(timeCodeString,"%02d:%02d:%02d:%02d", ulHrs, ulMins, ulSecs, ulFrms); // non-drop uses ':'
708 
709  _sHMSF = timeCodeString;
710 
711  // Initialize the rp188 struct with TC and set all other fields to zero
712  ConvertTcStrToReg();
713 
714  _bInitialized = true;
715  _bFresh = false; // we need to see the DBB reg to know...
716  SetVaricamFrameActive(false, 0);
717  SetVaricamFrameActive(false, 1);
718 
719  SetDropFrame(bDropFrame);
720  SetColorFrame(false);
721  SetVaricamRate( DefaultFrameRateForTimecodeFormat(_tcFormat) );
722 
723  if ( !FormatIs60_50fps(_tcFormat) ) // if we're using 50 or 60 fps format, the field id signifies frame pairs
724  SetFieldID(0);
725 
726  SetBFGBits(false, false, false);
727 
728  //printf("RP188 _rp188.Low = %x, _rp188.High = %x, _rp188.DBB = %x, tcS = %s\n", _rp188.Low, _rp188.High, _rp188.DBB, _sHMSF.c_str());
729 }
730 
731 
732 
733 
734 void CRP188::SetDropFrame(bool bDropFrameFlag)
735 {
736  // Set member var and rp188 struct bit
737  _bDropFrameFlag = bDropFrameFlag;
738  if (bDropFrameFlag == true)
739  _rp188.Low |= BIT_10;
740  else
741  _rp188.Low &= ~BIT_10;
742 }
743 
744 void CRP188::SetColorFrame(bool bColorFrameFlag)
745 {
746  // Set member var and rp188 struct bit
747  _bColorFrameFlag = bColorFrameFlag;
748  if (bColorFrameFlag == true)
749  _rp188.Low |= BIT_11;
750  else
751  _rp188.Low &= ~BIT_11;
752 }
753 
754 void CRP188::SetVaricamFrameActive(bool bVaricamActive, ULWord frame)
755 {
756  if (frame == 0)
757  {
758  _bVaricamActiveF0 = bVaricamActive;
759  if (bVaricamActive)
760  _rp188.Low |= BIT_5;
761  else
762  _rp188.Low &= ~BIT_5;
763  }
764  else
765  {
766  _bVaricamActiveF1 = bVaricamActive;
767  if (bVaricamActive)
768  _rp188.Low |= BIT_4;
769  else
770  _rp188.Low &= ~BIT_4;
771  }
772 }
773 
775 {
776  ULWord rate;
777 
778  switch (frameRate)
779  {
780  case NTV2_FRAMERATE_6000:
781  case NTV2_FRAMERATE_5994:
782  rate = 0x60;
783  break;
784 
785  case NTV2_FRAMERATE_5000:
786  rate = 0x50;
787  break;
788 
789  case NTV2_FRAMERATE_4800:
790  case NTV2_FRAMERATE_4795:
791  rate = 0x48;
792  break;
793 
794  case NTV2_FRAMERATE_3000:
795  case NTV2_FRAMERATE_2997:
796  rate = 0x30;
797  break;
798 
799  case NTV2_FRAMERATE_2500:
800  rate = 0x25;
801  break;
802 
803  case NTV2_FRAMERATE_2400:
804  case NTV2_FRAMERATE_2398:
805  rate = 0x24;
806  break;
807  case NTV2_FRAMERATE_1500:
808  case NTV2_FRAMERATE_1498:
809  rate = 0x15;
810  break;
811  default:
812  rate = 0;
813  break;
814  }
815  _rp188.Low &= 0x0F0FFFFF;
816  _rp188.Low |= (rate & 0x0f) << 20;
817  _rp188.Low |= (rate & 0xf0) << 24; // we really shift over to last group but nibble is already 4 bits over
818 }
819 
820 
822 {
823  _fieldID = fieldID;
824 
825  if ( FormatIsPAL(_tcFormat) )
826  {
827  if (fieldID)
828  _rp188.High |= BIT_27; // Note: PAL is bit 27 of HIGH word
829  else
830  _rp188.High &= ~BIT_27;
831  }
832  else
833  {
834  if (fieldID)
835  _rp188.Low |= BIT_27; // NTSC is bit 27 of LOW word
836  else
837  _rp188.Low &= ~BIT_27;
838  }
839 }
840 
842 {
843  bool bResult = (_fieldID != 0);
844 
845  if ( FormatIsPAL(_tcFormat) )
846  bResult = ((_rp188.High & BIT_27) != 0); // Note: PAL is bit 27 of HIGH word
847  else
848  bResult = ((_rp188.Low & BIT_27) != 0); // NTSC is bit 27 of LOW word
849 
850  return bResult;
851 }
852 
853 void CRP188::SetBFGBits(bool bBFG0, bool bBFG1, bool bBFG2)
854 {
855  // Same place for 60Hz and 50Hz
856  if (bBFG1)
857  _rp188.High |= BIT_26;
858  else
859  _rp188.High &= ~BIT_26;
860 
861 
862  if ( FormatIsPAL(_tcFormat) )
863  {
864  if (bBFG0)
865  _rp188.Low |= BIT_27;
866  else
867  _rp188.Low &= ~BIT_27;
868 
869  if (bBFG2)
870  _rp188.High |= BIT_11;
871  else
872  _rp188.High &= ~BIT_11;
873  }
874  else
875  {
876  if (bBFG0)
877  _rp188.High |= BIT_11;
878  else
879  _rp188.High &= ~BIT_11;
880 
881  if (bBFG2)
882  _rp188.High |= BIT_27;
883  else
884  _rp188.High &= ~BIT_27;
885  }
886 }
887 
888 
890 {
891  _rp188.DBB = (_rp188.DBB & ~0xFF000000) | (src << 24);
892 }
893 
894 
896 {
897  ULWord val = (_rp188.DBB & 0xFF000000) >> 24;
898  return (UByte) val;
899 }
900 
902 {
903  _rp188.DBB = (_rp188.DBB & ~0x000000FF) | (src);
904 }
905 
906 
908 {
909  ULWord val = (_rp188.DBB & 0x000000FF);
910  return (UByte) val;
911 }
912 
913 
914 
915 //--------------------------------------------------------------------------------------------------------------------
916 // Getters
917 //--------------------------------------------------------------------------------------------------------------------
918 bool CRP188::GetRP188Str (string & sRP188) const
919 {
920  sRP188 = _sHMSF;
921  return _bInitialized;
922 }
923 
924 const char *CRP188::GetRP188CString () const
925 {
926  return ( _sHMSF.c_str() );
927 }
928 
929 bool CRP188::GetRP188Frms (ULWord & ulFrms) const
930 {
931  ulFrms = _ulVal[0];
932  return _bInitialized;
933 }
934 
935 bool CRP188::GetRP188Secs (ULWord & ulSecs) const
936 {
937  ulSecs = _ulVal[1];
938  return _bInitialized;
939 }
940 
941 bool CRP188::GetRP188Mins (ULWord & ulMins) const
942 {
943  ulMins = _ulVal[2];
944  return _bInitialized;
945 }
946 
947 bool CRP188::GetRP188Hrs (ULWord & ulHrs) const
948 {
949  ulHrs = _ulVal[3];
950  return _bInitialized;
951 }
952 
953 bool CRP188::GetFrameCount (ULWord & frameCount)
954 {
955  ConvertTimecode (frameCount, _tcFormat, _ulVal[3], _ulVal[2], _ulVal[1], _ulVal[0]);
956 
957  return _bInitialized;
958 }
959 
960 
961 void CRP188::ConvertTimecode (ULWord & frameCount, TimecodeFormat format, ULWord hours, ULWord minutes, ULWord seconds, ULWord frames)
962 {
963  ULWord frms = 0;
964 
965  if (!FormatIsDropFrame(format) )
966  {
967  // non-drop
968  int mins = (60 * hours) + minutes; // 60 minutes / hour
969  int secs = (60 * mins) + seconds; // 60 seconds / minute
970  frms = (FramesPerSecond(format) * secs) + frames; // frames / second
971  }
972 
973  else
974  {
975  ULWord framesPerSec = FramesPerSecond(format);
976  ULWord framesPerMin = framesPerSec * 60; // 60 seconds/minute
977 
978  ULWord droppedFrames = (format == kTCFormat60fpsDF ? 4 : 2); // number of frames dropped in a "drop second"
979  ULWord dropFramesPerSec = framesPerSec - droppedFrames; // "drop-seconds" have all frames but two (or 4)...
980  ULWord dropframesPerMin = (59 * framesPerSec) + dropFramesPerSec; // "drop-minutes" have 1 drop and 59 regular seconds
981  ULWord dropframesPerTenMin = (9 * dropframesPerMin) + framesPerMin; // every ten minutes we get 1 regular and 9 drop minutes
982  ULWord dropframesPerHr = dropframesPerTenMin * 6; // 60 minutes/hr.
983 
984  frms = hours * dropframesPerHr; // convert hours
985 
986  int tenMins = minutes / 10;
987  frms += tenMins * dropframesPerTenMin; // convert 10's of minutes
988 
989  int mins = minutes % 10; // convert minutes
990  if (mins > 0)
991  {
992  frms += framesPerMin; // the first minute (out of ten) is always a non-drop
993  mins--;
994 
995  frms += mins * dropframesPerMin; // the rest are drop frame minutes
996  }
997 
998  int secs = seconds; // convert seconds
999  if (secs > 0)
1000  {
1001  if (_ulVal[2] % 10 != 0) // if this is a drop-minute
1002  {
1003  frms += dropFramesPerSec; // the first second (out of 59) is always a drop
1004  secs--;
1005  }
1006 
1007  frms += secs * framesPerSec; // the rest are regular seconds
1008  }
1009 
1010  if (seconds == 0 && minutes % 10 != 0) // convert frames1
1011  {
1012  if (frames >= droppedFrames)
1013  frms += (frames - droppedFrames); // if this is a "drop-second", the frame count has been offset by droppedFrames (e.g. 2 - 29 instead of 0 - 27)
1014  else
1015  frms += 0; // this shouldn't happen in dropframe format...
1016  }
1017  else
1018  frms += frames; // otherwise count all frames
1019  }
1020 
1021  frameCount = frms;
1022 }
1023 
1024 
1025  // convert a frame count to hours/minutes/seconds/frames (where frameCount "0" = 00:00:00:00)
1026 void CRP188::ConvertFrameCount (ULWord frameCount, TimecodeFormat format, ULWord & hours, ULWord & minutes, ULWord & seconds, ULWord & frames)
1027 {
1028  // non-dropframe
1029  ULWord framesPerSec = FramesPerSecond(format);
1030  ULWord framesPerMin = framesPerSec * 60; // 60 seconds/minute
1031  ULWord framesPerHr = framesPerMin * 60; // 60 minutes/hr.
1032  ULWord framesPerDay = framesPerHr * 24; // 24 hours/day
1033 
1034  if ( !FormatIsDropFrame(format) )
1035  {
1036  // non-dropframe
1037  // make sure we don't have more than 24 hours worth of frames
1038  frameCount = frameCount % framesPerDay;
1039 
1040  // how many hours?
1041  hours = frameCount / framesPerHr;
1042  frameCount = frameCount % framesPerHr;
1043 
1044  // how many minutes?
1045  minutes = frameCount / framesPerMin;
1046  frameCount = frameCount % framesPerMin;
1047 
1048  // how many seconds?
1049  seconds = frameCount / framesPerSec;
1050 
1051  // what's left is the frame count
1052  frames = frameCount % framesPerSec;
1053  }
1054 
1055  else
1056  {
1057  // dropframe
1058  ULWord droppedFrames = (_tcFormat == kTCFormat60fpsDF ? 4 : 2); // number of frames dropped in a "drop second"
1059  ULWord dropFramesPerSec = framesPerSec - droppedFrames;
1060  ULWord dropframesPerMin = (59 * framesPerSec) + dropFramesPerSec; // every minute we get 1 drop and 59 regular seconds
1061  ULWord dropframesPerTenMin = (9 * dropframesPerMin) + framesPerMin; // every ten minutes we get 1 regular and 9 drop minutes
1062  ULWord dropframesPerHr = dropframesPerTenMin * 6; // 60 minutes/hr.
1063  ULWord dropframesPerDay = dropframesPerHr * 24; // 24 hours/day
1064 
1065  // make sure we don't have more than 24 hours worth of frames
1066  frameCount = frameCount % dropframesPerDay;
1067 
1068  // how many hours?
1069  hours = frameCount / dropframesPerHr;
1070  frameCount = frameCount % dropframesPerHr;
1071 
1072  // how many tens of minutes?
1073  minutes = 10 * (frameCount / dropframesPerTenMin);
1074  frameCount = frameCount % dropframesPerTenMin;
1075 
1076  // how many units of minutes?
1077  if (frameCount >= framesPerMin)
1078  {
1079  minutes += 1; // got at least one minute (the first one is a non-drop minute)
1080  frameCount = frameCount - framesPerMin;
1081 
1082  // any remaining minutes are drop-minutes
1083  minutes += frameCount / dropframesPerMin;
1084  frameCount = frameCount % dropframesPerMin;
1085  }
1086 
1087  // how many seconds? depends on whether this was a regular or a drop minute...
1088  seconds = 0;
1089  if (minutes % 10 == 0)
1090  {
1091  // regular minute: all seconds are full length
1092  seconds = frameCount / framesPerSec;
1093  frameCount = frameCount % framesPerSec;
1094  }
1095 
1096  else
1097  {
1098  // drop minute: the first second is a drop second
1099  if (frameCount >= dropFramesPerSec)
1100  {
1101  seconds += 1; // got at least one (the first one is a drop second)
1102  frameCount = frameCount - dropFramesPerSec;
1103 
1104  // any remaining seconds are full-length
1105  seconds += frameCount / framesPerSec;
1106  frameCount = frameCount % framesPerSec;
1107  }
1108  }
1109 
1110  // what's left is the frame count
1111  frames = frameCount;
1112 
1113  // if we happened to land on a drop-second, add 2 frames (the 28 frames are numbered 2 - 29, not 0 - 27)
1114  if ( (seconds == 0) && (minutes % 10 != 0))
1115  frames += droppedFrames;
1116  }
1117 }
1118 
1119 
1120  // Add <frameCount> frames to current timecode
1121  // Accounts for 24-hr wrap in whatever format we're currently in
1123 {
1124  ULWord currentFrameCount, newFrameCount;
1125  GetFrameCount(currentFrameCount);
1126 
1127  // add
1128  newFrameCount = currentFrameCount + frameCount;
1129 
1130  // check for 24-hr rollover
1131  newFrameCount = newFrameCount % MaxFramesPerDay();
1132 
1133  SetRP188 (newFrameCount, _tcFormat);
1134 
1135  return newFrameCount;
1136 }
1137 
1138 
1139  // Subtract <frameCount> frames from current timecode
1140  // Accounts for 24-hr wrap in whatever format we're currently in
1142 {
1143  ULWord currentFrameCount, newFrameCount;
1144  GetFrameCount(currentFrameCount);
1145 
1146  // make sure the amount we want to subtract is < 24 hrs.
1147  ULWord maxFrames = MaxFramesPerDay();
1148  ULWord subAmt = frameCount % maxFrames;
1149 
1150  if (subAmt <= currentFrameCount)
1151  newFrameCount = currentFrameCount - subAmt; // no wrap - just subtract
1152  else
1153  newFrameCount = maxFrames - (subAmt - currentFrameCount); // deal with 24 hr "underflow"
1154 
1155  SetRP188 (newFrameCount, _tcFormat);
1156 
1157  return newFrameCount;
1158 }
1159 
1160 
1161  // returns the total number of frames in a 24 hr day for the given format
1163 {
1164  ULWord result = 0;
1165 
1166  if (format == kTCFormatUnknown)
1167  format = _tcFormat;
1168 
1169  ULWord framesPerSec = FramesPerSecond(format);
1170  ULWord framesPerMin = framesPerSec * 60; // 60 seconds/minute
1171 
1172  if ( !FormatIsDropFrame(format) )
1173  {
1174  // non-drop frame
1175  ULWord framesPerHr = framesPerMin * 60; // 60 minutes/hr.
1176  result = framesPerHr * 24; // 24 hours/day
1177  }
1178  else
1179  {
1180  ULWord droppedFrames = (_tcFormat == kTCFormat60fpsDF ? 4 : 2); // number of frames dropped in a "drop second"
1181  ULWord dropframesPerMin = framesPerMin - droppedFrames; // "drop-minutes" have all of the frames but two...
1182  ULWord dropframesPerTenMin = (9 * dropframesPerMin) + framesPerMin; // every ten minutes we get 1 regular and 9 drop minutes
1183  ULWord dropframesPerHr = dropframesPerTenMin * 6; // 60 minutes/hr.
1184  result = dropframesPerHr * 24; // 24 hours/day
1185  }
1186 
1187  return result;
1188 }
1189 
1190 
1191  // FormatIsDropFrame()
1192  // returns 'true' if the designated time code format is one of the "drop frame" formats
1194 {
1195  bool bResult = false;
1196 
1197  if (format == kTCFormatUnknown)
1198  format = _tcFormat;
1199 
1200  if (format == kTCFormat30fpsDF || format == kTCFormat60fpsDF)
1201  bResult = true;
1202 
1203  return bResult;
1204 }
1205 
1206  // FormatIs60_50fps()
1207  // returns 'true' if the designated time code format is greater than 39 fps
1208  // (requires using FieldID bit to store ls bit of frame "10s" count)
1210 {
1211  bool bResult = false;
1212 
1213  if (format == kTCFormatUnknown)
1214  format = _tcFormat;
1215 
1216  if (format == kTCFormat60fps ||
1217  format == kTCFormat60fpsDF ||
1218  format == kTCFormat48fps ||
1219  format == kTCFormat50fps)
1220  bResult = true;
1221 
1222  return bResult;
1223 }
1224 
1225  // FormatIsPAL()
1226  // returns 'true' if the designated time code format is one of the "PAL" formats
1227  // (uses different bit allocations for timecode status "flags")
1229 {
1230  bool bResult = false;
1231 
1232  if (format == kTCFormatUnknown)
1233  format = _tcFormat;
1234 
1235  if (format == kTCFormat25fps || format == kTCFormat50fps)
1236  bResult = true;
1237 
1238  return bResult;
1239 }
1240 
1241 bool CRP188::GetRP188Reg (RP188_STRUCT & rp188) const
1242 {
1243  rp188 = _rp188;
1244  return _bInitialized;
1245 }
1246 
1247 bool CRP188::GetRP188Reg (NTV2_RP188 & outRP188) const
1248 {
1249  outRP188 = _rp188;
1250  return _bInitialized;
1251 }
1252 
1253 bool CRP188::GetRP188UserBitsStr (string & sRP188UB)
1254 {
1255  // Derive the userbits and userbits string from the rp188 struct
1256  RP188ToUserBits();
1257 
1258  sRP188UB = _sUserBits;
1259  return _bInitialized;
1260 }
1261 
1263 {
1264  // Derive the userbits and userbits string from the rp188 struct
1265  RP188ToUserBits();
1266 
1267  return ( _sUserBits.c_str() );
1268 }
1269 
1271 {
1272  ULWord result = 0;
1273 
1274  // Derive the userbits and userbits string from the rp188 struct
1275  RP188ToUserBits();
1276 
1277  // note: SMPTE labels the Binary Groups 1 - 8, but we store them in a zero-based array
1278  if ( (smpteNum >= 1) && (smpteNum <= 8) )
1279  result = _ulUserBits[smpteNum-1];
1280 
1281  return result;
1282 }
1283 
1284 bool CRP188::SetBinaryGroup (ULWord smpteNum, ULWord bits)
1285 {
1286  // note: SMPTE labels the Binary Groups 1 - 8, but we store them in a zero-based array
1287  if ( (smpteNum >= 1) && (smpteNum <= 8) )
1288  {
1289  _ulUserBits[smpteNum-1] = bits;
1290 
1291  if ( smpteNum < 5 )
1292  {
1293  ULWord newBits = _rp188.Low;
1294  ULWord shift = (smpteNum-1) * 8 + 4;
1295 
1296  newBits &= ~(0xF << shift);
1297  _rp188.Low = newBits | ((bits & 0xF) << shift);
1298  }
1299  else
1300  {
1301  ULWord newBits = _rp188.High;
1302  ULWord shift = (smpteNum-5) * 8 + 4;
1303 
1304  newBits &= ~(0xF << shift);
1305  _rp188.High = newBits | ((bits & 0xF) << shift);
1306  }
1307 
1308  return true;
1309  }
1310 
1311  return false;
1312 }
1313 
1315 {
1316  _ulUserBits[7] = (bits >> 28) & 0xF; // Binary Group 8
1317  _ulUserBits[6] = (bits >> 24) & 0xF; // Binary Group 7
1318  _ulUserBits[5] = (bits >> 20) & 0xF; // Binary Group 6
1319  _ulUserBits[4] = (bits >> 16) & 0xF; // Binary Group 5
1320  _ulUserBits[3] = (bits >> 12) & 0xF; // Binary Group 4
1321  _ulUserBits[2] = (bits >> 8) & 0xF; // Binary Group 3
1322  _ulUserBits[1] = (bits >> 4) & 0xF; // Binary Group 2
1323  _ulUserBits[0] = (bits >> 0) & 0xF; // Binary Group 1
1324 
1325  ULWord newHigh = _rp188.High & 0x0F0F0F0F;
1326  ULWord newLow = _rp188.Low & 0x0F0F0F0F;
1327 
1328  newHigh |= ((bits & 0xF0000000) >> 0) |
1329  ((bits & 0x0F000000) >> 4) |
1330  ((bits & 0x00F00000) >> 8) |
1331  ((bits & 0x000F0000) >> 12);
1332  newLow |= ((bits & 0x0000F000) << 16) |
1333  ((bits & 0x00000F00) << 12) |
1334  ((bits & 0x000000F0) << 8) |
1335  ((bits & 0x0000000F) << 4);
1336 
1337  _rp188.High = newHigh;
1338  _rp188.Low = newLow;
1339 
1340  return true;
1341 }
1342 
1344 {
1345  ULWord result = 0;
1346 
1347  // note: SMPTE labels the UDWs 1 - 16! (i.e. NOT zero-based!)
1348  if ( (smpteUDW >= 1) && (smpteUDW <= 16) )
1349  {
1350  int index = smpteUDW - 1; // make it zero-based
1351 
1352  if (index < 8)
1353  result = (_rp188.Low >> (4 * index)) & 0x0F; // 0 - 7 come from bits 0 - 31
1354  else
1355  result = (_rp188.High >> (4 * (index-8))) & 0x0F; // 8 - 15 come from bits 32 - 63
1356  }
1357 
1358  return result;
1359 }
1360 
1362 {
1363  // the VariCam "Shooting Frame Rate" is encodec as BCD digits in
1364  // Binary Groups 4 (tens) and 3 (ones).
1365  return ( (BinaryGroup(4) * 10) + BinaryGroup(3) );
1366 }
1367 
1368 
1369  // note: this doesn't deal (accurately) with drop-frame
1371 {
1372  ULWord fps = 30;
1373 
1374  if (format == kTCFormatUnknown)
1375  format = _tcFormat;
1376 
1377  switch (format)
1378  {
1379  case kTCFormat24fps: fps = 24; break;
1380  case kTCFormat25fps: fps = 25; break;
1381  case kTCFormat30fps:
1382  case kTCFormat30fpsDF: fps = 30; break;
1383  case kTCFormat48fps: fps = 48; break;
1384  case kTCFormat50fps: fps = 50; break;
1385  case kTCFormat60fps:
1386  case kTCFormat60fpsDF: fps = 60; break;
1387 
1388  default: fps = 30; break;
1389  }
1390 
1391  return fps;
1392 }
1393 
1394 
1395  // note: this is just for taking a stab at a default NTV2FrameRate based on an incoming timecode format
1396  // since there are MANY operational conditions where non-default frame rates vs timecode formats come up
1397  // (e.g. 720p60 uses 30 fps timecode, or 30 fps timecode could be 29.97 or 30 fps, etc...) the user should
1398  // NOT rely on this default to "always work" for their specific case.
1400 {
1401  if (format == kTCFormatUnknown)
1402  format = _tcFormat;
1403 
1405 
1406  switch (format)
1407  {
1408  case kTCFormat24fps: result = NTV2_FRAMERATE_2400; break;
1409  case kTCFormat25fps: result = NTV2_FRAMERATE_2500; break;
1410  case kTCFormat30fps: result = NTV2_FRAMERATE_3000; break;
1411  case kTCFormat30fpsDF: result = NTV2_FRAMERATE_3000; break;
1412  case kTCFormat48fps: result = NTV2_FRAMERATE_5000; break;
1413  case kTCFormat50fps: result = NTV2_FRAMERATE_5000; break;
1414  case kTCFormat60fps: result = NTV2_FRAMERATE_6000; break;
1415  case kTCFormat60fpsDF: result = NTV2_FRAMERATE_6000; break;
1416 
1417  default: result = NTV2_FRAMERATE_UNKNOWN; break;
1418  }
1419 
1420  return result;
1421 }
1422 
1423 
1424 //--------------------------------------------------------------------------------------------------------------------
1425 // Private
1426 //--------------------------------------------------------------------------------------------------------------------
1427 // Convert Timecode string to integer value
1428 void CRP188::ConvertTcStrToVal (void)
1429 {
1430  int iOff;
1431  for (int i = 0; i < 4; i++)
1432  {
1433  iOff = i * 3; // 2 spaces for 'xx' + 1 space for ':'
1434  string s(_sHMSF, iOff, 2); // s starts at iOff and goes 2 spaces
1435 
1436  istringstream ist(s); // turn s into ist, a string stream
1437 
1438  ist >> _ulVal[3 - i]; // convert from string to number
1439  }
1440 }
1441 
1442 void CRP188::ConvertTcStrToReg (void)
1443 {
1444  memset ((void *) &_rp188, 0, sizeof(_rp188));
1445  char pcBuf[2];
1446 
1447  // Tens of hours
1448  int iOff = 0, iSingle;
1449  pcBuf[0] = _sHMSF[iOff];
1450  pcBuf[1] = 0;
1451  sscanf (pcBuf, "%d", &iSingle);
1452  _rp188.High |= (iSingle & 0x3) << 24;
1453 
1454  // Units of hours
1455  iOff = 1;
1456  pcBuf[0] = _sHMSF[iOff];
1457  sscanf (pcBuf, "%d", &iSingle);
1458  _rp188.High |= (iSingle & 0xF) << 16;
1459 
1460  // Tens of minutes
1461  iOff = 3;
1462  pcBuf[0] = _sHMSF[iOff];
1463  sscanf (pcBuf, "%d", &iSingle);
1464  _rp188.High |= (iSingle & 0x7) << 8;
1465 
1466  // Units of minutes
1467  iOff = 4;
1468  pcBuf[0] = _sHMSF[iOff];
1469  sscanf (pcBuf, "%d", &iSingle);
1470  _rp188.High |= (iSingle & 0xF);
1471 
1472  // Tens of seconds
1473  iOff = 6;
1474  pcBuf[0] = _sHMSF[iOff];
1475  sscanf (pcBuf, "%d", &iSingle);
1476  _rp188.Low |= (iSingle & 0x7) << 24;
1477 
1478  // Units of seconds
1479  iOff = 7;
1480  pcBuf[0] = _sHMSF[iOff];
1481  sscanf (pcBuf, "%d", &iSingle);
1482  _rp188.Low |= (iSingle & 0xF) << 16;
1483 
1484  if ( !FormatIs60_50fps() )
1485  {
1486  // Tens of frames
1487  iOff = 9;
1488  pcBuf[0] = _sHMSF[iOff];
1489  sscanf (pcBuf, "%d", &iSingle);
1490  _rp188.Low |= (iSingle & 0x3) << 8;
1491 
1492  // Units of frames
1493  iOff = 10;
1494  pcBuf[0] = _sHMSF[iOff];
1495  sscanf (pcBuf, "%d", &iSingle);
1496  _rp188.Low |= (iSingle & 0xF);
1497  }
1498  else
1499  {
1500  // For frame rates >= 40 fps, we need an extra bit for the frame "10s" digit. By convention, we use the FieldID
1501  // bit as the LS bit of the 3-bit field (in essence, dividing by two and using the FID bit as a "half-frame")
1502  // Tens of frames
1503  int iTens;
1504  iOff = 9;
1505  pcBuf[0] = _sHMSF[iOff];
1506  sscanf (pcBuf, "%d", &iTens);
1507 
1508  // Units of frames
1509  int iUnits;
1510  iOff = 10;
1511  pcBuf[0] = _sHMSF[iOff];
1512  sscanf (pcBuf, "%d", &iUnits);
1513 
1514  ULWord frameCount = (10 * iTens) + iUnits;
1515  if (frameCount >= FramesPerSecond()) // limit-check
1516  frameCount = FramesPerSecond() - 1;
1517 
1518  // LS bit
1519  SetFieldID(frameCount % 2);
1520  frameCount /= 2;
1521 
1522  _rp188.Low |= ((frameCount / 10) & 0x3) << 8; // Tens of frames (ms 2 bits)
1523  _rp188.Low |= ((frameCount % 10) & 0xF) ; // Units of frames
1524  }
1525 }
1526 
1527 void CRP188::RP188ToUserBits (void)
1528 {
1529  char userBitsString[12];
1530 
1531  _ulUserBits[7] = (_rp188.High >> 28) & 0xF; // Binary Group 8
1532  userBitsString[0] = hexChar[_ulUserBits[7]];
1533 
1534  _ulUserBits[6] = (_rp188.High >> 20) & 0xF; // Binary Group 7
1535  userBitsString[1] = hexChar[_ulUserBits[6]];
1536  userBitsString[2] = ' ';
1537 
1538  _ulUserBits[5] = (_rp188.High >> 12) & 0xF; // Binary Group 6
1539  userBitsString[3] = hexChar[_ulUserBits[5]];
1540 
1541  _ulUserBits[4] = (_rp188.High >> 4) & 0xF; // Binary Group 5
1542  userBitsString[4] = hexChar[_ulUserBits[4]];
1543  userBitsString[5] = ' ';
1544 
1545  _ulUserBits[3] = (_rp188.Low >> 28) & 0xF; // Binary Group 4
1546  userBitsString[6] = hexChar[_ulUserBits[3]];
1547 
1548  _ulUserBits[2] = (_rp188.Low >> 20) & 0xF; // Binary Group 3
1549  userBitsString[7] = hexChar[_ulUserBits[2]];
1550  userBitsString[8] = ' ';
1551 
1552  _ulUserBits[1] = (_rp188.Low >> 12) & 0xF; // Binary Group 2
1553  userBitsString[9] = hexChar[_ulUserBits[1]];
1554 
1555  _ulUserBits[0] = (_rp188.Low >> 4) & 0xF; // Binary Group 1
1556  userBitsString[10] = hexChar[_ulUserBits[0]];
1557  userBitsString[11] = '\0';
1558 
1559  _sUserBits = userBitsString;
1560 }
1561 
1562 
1563 
1564 bool CRP188::InitBurnIn (NTV2FrameBufferFormat frameBufferFormat, NTV2FrameDimensions frameDimensions, LWord percentY)
1565 {
1566  bool bResult = true;
1567 
1568  // see if we've already rendered this format/size
1569  if (_bRendered && _pCharRenderMap != NULL && frameBufferFormat == _charRenderFBF && frameDimensions.Height() == _charRenderHeight && frameDimensions.Width() == _charRenderWidth)
1570  {
1571  return bResult; // already rendered...
1572  }
1573 
1574  else
1575  {
1576  // these are the pixel formats we know how to do...
1577  bool bFormatOK (true);
1578  int bytesPerPixel (0);
1579  switch (frameBufferFormat)
1580  {
1581  case NTV2_FBF_8BIT_YCBCR:
1582  bytesPerPixel = 2;
1583  break;
1584 
1585  case NTV2_FBF_ABGR:
1586  bytesPerPixel = 4;
1587  break;
1588 
1589  case NTV2_FBF_ARGB:
1590  bytesPerPixel = 4;
1591  break;
1592 
1593  case NTV2_FBF_10BIT_YCBCR:
1594  bytesPerPixel = 3; // not really - we'll have to override this wherever "bytesPerPixel" is used below...
1595  break;
1596 
1597  case NTV2_FBF_10BIT_DPX:
1598  bytesPerPixel = 4;
1599  break;
1600 
1601  default: bFormatOK = false;
1602  break;
1603  }
1604 
1605  if (bFormatOK)
1606  {
1607  // scale the characters based on the frame size they'll be used in
1608  int dotScale = 1; // SD scale
1609  if (frameDimensions.Height() > 900)
1610  dotScale = 3; // HD 1080
1611  else if (frameDimensions.Height() > 650)
1612  dotScale = 2; // HD 720
1613 
1614  int dotWidth = 1 * dotScale; // pixels per "dot"
1615  int dotHeight = 2 * dotScale; // frame lines per "dot"
1616 
1617  // exceptions: if this is DVCProHD or HDV, we're working with horizontally-scaled pixels. Tweak the dotWidth to compensate.
1618  if (frameDimensions.Height() > 900 && frameDimensions.Width() <= 1440)
1619  dotWidth = 2; // 1280x1080 or 1440x1080
1620 
1621 // else if (frameDimensions.Height() > 650 && frameDimensions.Width() < 1100)
1622 // dotWidth = 1; // 960x720
1623 
1624  int charWidthBytes = kDigitDotWidth * dotWidth * bytesPerPixel;
1625  if (frameBufferFormat == NTV2_FBF_10BIT_YCBCR)
1626  charWidthBytes = (kDigitDotWidth * dotWidth * 16) / 6; // note: assumes kDigitDotWidth is evenly divisible by 6!
1627 
1628  int charHeightLines = kDigitDotHeight * dotHeight;
1629 
1630  // if we had a previous render map, free it now
1631  if (_pCharRenderMap != NULL)
1632  {
1633  free(_pCharRenderMap);
1634  _pCharRenderMap = NULL;
1635  }
1636 
1637  // malloc space for a new render map
1638  _pCharRenderMap = (char*)malloc(kMaxTCChars * charWidthBytes * charHeightLines);
1639  if (_pCharRenderMap != NULL)
1640  {
1641  char *pRenderMap = _pCharRenderMap;
1642 
1643  // for each character...
1644  for (int c = 0; c < kMaxTCChars; c++)
1645  {
1646  // for each scan line...
1647  for (int y = 0; y < kDigitDotHeight; y++)
1648  {
1649  // each rendered line is duplicated N times
1650  for (int ydup = 0; ydup < dotHeight; ydup++)
1651  {
1652  // each dot...
1653  for (int x = 0; x < kDigitDotWidth; x++)
1654  {
1655  char dot = CharMap[c][y][x];
1656 
1657  if (frameBufferFormat == NTV2_FBF_8BIT_YCBCR)
1658  {
1659  char val = 0;
1660  switch (dot)
1661  {
1662  case 0: val = char(0x040 >> 2); break; // 16
1663  case 1: val = char(0x164 >> 2); break; // 89
1664  case 2: val = char(0x288 >> 2); break; // 162
1665  case 3: val = char(0x3AC >> 2); break; // 235
1666  }
1667 
1668  // each rendered pixel is duplicated N times
1669  for (int xdup = 0; xdup < dotWidth; xdup++)
1670  {
1671  *pRenderMap++ = char(0x80); // C
1672  *pRenderMap++ = val; // Y
1673  }
1674  }
1675 
1676  else if (frameBufferFormat == NTV2_FBF_10BIT_YCBCR)
1677  {
1678  int val = 0;
1679  switch (dot)
1680  {
1681  case 0: val = 0x040; break; // 64
1682  case 1: val = 0x164; break; // 356
1683  case 2: val = 0x288; break; // 648
1684  case 3: val = 0x3AC; break; // 940
1685  }
1686 
1687  // each rendered pixel is duplicated N times
1688  for (int xdup = 0; xdup < dotWidth; xdup++)
1689  {
1690  writeV210Pixel (&pRenderMap, ((x * dotWidth) + xdup), 0x200, val);
1691  }
1692  }
1693 
1694  else if (frameBufferFormat == NTV2_FBF_ABGR || frameBufferFormat == NTV2_FBF_ARGB )
1695  {
1696  char val = 0;
1697  switch (dot)
1698  {
1699  case 0: val = (char)0x00; break;
1700  case 1: val = (char)0x55; break;
1701  case 2: val = (char)0xaa; break;
1702  case 3: val = (char)0xff; break;
1703  }
1704 
1705  // each rendered pixel is duplicated N times
1706  for (int xdup = 0; xdup < dotWidth; xdup++)
1707  {
1708  *pRenderMap++ = 0; // A
1709  *pRenderMap++ = val; // R
1710  *pRenderMap++ = val; // G
1711  *pRenderMap++ = val; // B
1712  }
1713  }
1714 
1715  else if ( frameBufferFormat == NTV2_FBF_ARGB )
1716  {
1717  char val = 0;
1718  switch (dot)
1719  {
1720  case 0: val = (char)0x00; break;
1721  case 1: val = (char)0x55; break;
1722  case 2: val = (char)0xaa; break;
1723  case 3: val = (char)0xff; break;
1724  }
1725 
1726  // each rendered pixel is duplicated N times
1727  for (int xdup = 0; xdup < dotWidth; xdup++)
1728  {
1729  *pRenderMap++ = 0; // A
1730  *pRenderMap++ = val; // R
1731  *pRenderMap++ = val; // G
1732  *pRenderMap++ = val; // B
1733  }
1734  }
1735 
1736  else if (frameBufferFormat == NTV2_FBF_10BIT_DPX)
1737  {
1738  int val = 0;
1739  switch (dot)
1740  {
1741  case 0: val = 64; break;
1742  case 1: val = 356; break;
1743  case 2: val = 648; break;
1744  case 3: val = 940; break;
1745  }
1746 
1747  // each rendered pixel is duplicated N times
1748  for (int xdup = 0; xdup < dotWidth; xdup++)
1749  {
1750  *pRenderMap++ = ((val & 0x3fc) >> 2);
1751  *pRenderMap++ = ((val & 0x003) << 6) | ((val & 0x3f0) >> 4);
1752  *pRenderMap++ = ((val & 0x00f) << 4) | ((val & 0x3c0) >> 6);
1753  *pRenderMap++ = ((val & 0x03f) << 2);
1754  }
1755  }
1756  }
1757  }
1758  }
1759  }
1760 
1761  _bRendered = true;
1762  _charRenderFBF = frameBufferFormat;
1763  _charRenderHeight = frameDimensions.Height();
1764  _charRenderWidth = frameDimensions.Width();
1765 
1766  // character sizes
1767  _charWidthBytes = charWidthBytes;
1768  _charHeightLines = charHeightLines;
1769 
1770  // burn-in offset
1771  int byteWidth = (frameDimensions.Width() * bytesPerPixel);
1772  if (frameBufferFormat == NTV2_FBF_10BIT_YCBCR)
1773  byteWidth = (frameDimensions.Width() * 16) / 6; // in 10-bit YUV, 6 pixels = 16 bytes
1774 
1775  _charPositionX = (byteWidth - (kNumBurnInChars * charWidthBytes)) / 2; // assume centered
1776  if(percentY == 0)
1777  {
1778  _charPositionY = (frameDimensions.Height() * 8) / 10; // assume 80% of the way down the screen
1779  }
1780  else
1781  {
1782  _charPositionY = (frameDimensions.Height() * percentY) / 100;
1783  }
1784 
1785  // 10-bit YUV has to start on a 16-byte boundary in order to match the "cadence"
1786  if (frameBufferFormat == NTV2_FBF_10BIT_YCBCR)
1787  _charPositionX &= ~0x0f;
1788  }
1789  }
1790 
1791  else // we don't know how to do this pixel format...
1792  bResult = false;
1793  }
1794 
1795  return bResult;
1796 }
1797 
1798 
1799  // write a single chroma/luma pair of components
1800  // note that it's up to the caller to make sure that the chroma is the correct Cb or Cr,
1801  // and is properly timed with adjacent pixels!
1802 void CRP188::writeV210Pixel (char **pBytePtr, int x, int c, int y)
1803 {
1804  char *p = *pBytePtr;
1805 
1806  // the components in each v210 6-pixel block are laid out like this (note that the UInt32s are swixelled!):
1807  //
1808  // Addr: | 3 2 1 0 | 7 6 5 4 | 11 10 9 8 | 15 14 13 12 |
1809  // { 00 Cr0 Y0 Cb0 00 Y2 Cb2 Y1 00 Cb4 Y3 Cr2 00 Y5 Cr4 Y4 }
1810  //
1811  int cadence = x % 3;
1812 
1813  switch (cadence)
1814  {
1815  case 0: // Cb0/Y0 or Cr2/Y3: we assume that p points to byte 0/8. When we are finished, it will still point to byte 0/8
1816  p[0] = c & 0x0FF; // c<7:0>
1817  p[1] = (( y & 0x03F) << 2) + (( c & 0x300) >> 8); // y<5:0> + c<9:8>
1818  p[2] = (p[2] & 0x0F0) + (( y & 0x3C0) >> 6); // (merge) + y<9:6>
1819  break;
1820 
1821  case 1: // Cr0/Y1 or Cb4/Y4: we assume that p points to byte 0/8. When we are finished, it will point to byte 4/12
1822  p[2] = (( c & 0x00F) << 4) + (p[2] & 0x00F); // c<3:0> + (merge)
1823  p[3] = (( c & 0x3F0) >> 4); // '00' + c<9:4>
1824  p[4] = y & 0x0FF; // y<7:0>
1825  p[5] = (p[5] & 0x0FC) + (( y & 0x300) >> 8); // (merge) + y<9:8>
1826  *pBytePtr += 4;
1827  break;
1828 
1829  case 2: // Cb2/Y2 or Cr4/Y5: we assume that p points to byte 4/12. When we are finished, it will point to byte 8/16
1830  p[1] = (( c & 0x03F) << 2) + (p[1] & 0x003); // c<5:0> + (merge)
1831  p[2] = (( y & 0x00F) << 4) + (( c & 0x3C0) >> 6); // y<3:0> + c<9:6>
1832  p[3] = (( y & 0x3F0) >> 4); // '00' + y<9:4>
1833  *pBytePtr += 4;
1834  break;
1835  }
1836 }
1837 
1838 
1839 bool CRP188::BurnTC (char *pBaseVideoAddress, int rowBytes, TimecodeBurnMode burnMode, int64_t frameCount, bool bDisplay60_50fpsAs30_25)
1840 {
1841  int val, char1, char2, trailingChar = kMaxTCChars;
1842  int charSizeBytes = _charWidthBytes * _charHeightLines;
1843 
1844  if (_bRendered)
1845  {
1846  char *pFrameBuff = pBaseVideoAddress + (_charPositionY * rowBytes) + _charPositionX;
1847 
1848  if (burnMode == kTCBurnTimecode || burnMode == kTCBurnUserBits)
1849  {
1850  for (int dig = 0; dig < 4; dig++)
1851  {
1852  if (burnMode == kTCBurnUserBits)
1853  {
1854  char1 = BinaryGroup(8 - (2*dig)); // user bits ("Binary Group") data
1855  char2 = BinaryGroup(7 - (2*dig));
1856  }
1857  else // timecode
1858  {
1859  val = _ulVal[3-dig]; // timecode data
1860 
1861  // big ugly gross exception:
1862  // if the timecode format is >= 40 fps BUT we want to display the 2nd frame in the form: "XX:XX:XX:00*", where
1863  // the frame count runs from 0 - 29 (or 24) and '*' means "2nd frame", then we have to schmooze with the data...
1864  if ( dig == 3 // last digit (frames)
1865  && FormatIs60_50fps(_tcFormat) // timecode frame rate > 39 fps
1866  && bDisplay60_50fpsAs30_25 ) // we wanna convert it
1867  {
1868  trailingChar = (val % 2 == 0 ? kDigSpace : kDigAsterisk); // convert ls bit to trailing '*'
1869  val /= 2; // convert 0 - 59 frames to 0 - 29 frames
1870  }
1871 
1872  char1 = val / 10; // tens digit
1873  char2 = val % 10; // units digit
1874  }
1875 
1876  // sanity check
1877  char1 = (char1 < 0 ? 0 : (char1 > kMaxTCChars ? kDigSpace : char1) );
1878  char2 = (char2 < 0 ? 0 : (char2 > kMaxTCChars ? kDigSpace : char2) );
1879 
1880  // "tens" digit
1881  CopyDigit ( (_pCharRenderMap + (char1 * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1882  pFrameBuff += _charWidthBytes;
1883 
1884  // "ones" digit
1885  CopyDigit ( (_pCharRenderMap + (char2 * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1886  pFrameBuff += _charWidthBytes;
1887 
1888  // add a colon after each pair (except last)
1889  if (dig < 3)
1890  {
1891  if (dig == 2 && FormatIsDropFrame() )
1892  CopyDigit ( (_pCharRenderMap + (kDigSemicolon * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1893  else
1894  CopyDigit ( (_pCharRenderMap + (kDigColon * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1895  pFrameBuff += _charWidthBytes;
1896  }
1897  }
1898 
1899  // if there is a "trailing character" (sometimes used for Field ID), do it now
1900  if (trailingChar >= 0 && trailingChar < kMaxTCChars)
1901  {
1902  CopyDigit ( (_pCharRenderMap + (trailingChar * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1903  pFrameBuff += _charWidthBytes;
1904  }
1905  }
1906 
1907  else if (burnMode == kTCBurnBlank)
1908  {
1909  for (int dig = 0; dig < 4; dig++)
1910  {
1911  // 2 "dashes"
1912  CopyDigit ( (_pCharRenderMap + (kDigDash * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1913  pFrameBuff += _charWidthBytes;
1914 
1915  CopyDigit ( (_pCharRenderMap + (kDigDash * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1916  pFrameBuff += _charWidthBytes;
1917 
1918  if (dig < 3)
1919  {
1920  if (dig == 2 && FormatIsDropFrame() )
1921  CopyDigit ( (_pCharRenderMap + (kDigColon * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1922  else
1923  CopyDigit ( (_pCharRenderMap + (kDigColon * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1924  pFrameBuff += _charWidthBytes;
1925  }
1926  }
1927  }
1928 
1929  else // display frame count
1930  {
1931  // we have two possible formats: if we the user DOESN'T pass in a frameCount, we calculate the frame count
1932  // from the current timecode. Since it can be (at most) 7 digits in size, we display 7 digits with 2 spaces
1933  // on either side. If the user DOES pass in a frame count it could be larger in size (we're going to allow
1934  // up to 9 digits plus a sign), so we're going to display 9 digits with one space on either side.
1935 
1936  int64_t count = frameCount; // use passed-in frame count (allows for values outside the range of normal 24-hr timecode)
1937  int64_t scale = 1000000000; // 9 digit max
1938  int maxDigits = 9;
1939  int numSpaces = 1; // 1 + 9 + 1 = 11
1940  int i;
1941  if (count == kDefaultFrameCount)
1942  {
1943  ULWord tmpCount (0);
1944  GetFrameCount(tmpCount); // default = get current frame count
1945  count = tmpCount;
1946  scale = 10000000; // 7 digit max
1947  maxDigits = 7;
1948  numSpaces = 2; // 2 + 7 + 2 = 11
1949  }
1950 
1951  // 1 or 2 pre-spaces
1952  for (i = 0; i < numSpaces; i++)
1953  {
1954  // check for sign
1955  if (i == numSpaces-1)
1956  {
1957  if (count >= 0)
1958  CopyDigit ( (_pCharRenderMap + (kDigSpace * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1959  else
1960  {
1961  CopyDigit ( (_pCharRenderMap + (kDigDash * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1962  count = -count;
1963  }
1964  pFrameBuff += _charWidthBytes;
1965  }
1966  else
1967  {
1968  CopyDigit ( (_pCharRenderMap + (kDigSpace * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1969  pFrameBuff += _charWidthBytes;
1970  }
1971  }
1972 
1973  if (count >= scale)
1974  count = count % scale; // just wrap
1975 
1976  for (int dig = 0; dig < maxDigits; dig++)
1977  {
1978  scale = scale / 10;
1979 
1980  char1 = int(count / scale);
1981  CopyDigit ( (_pCharRenderMap + (char1 * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1982  pFrameBuff += _charWidthBytes;
1983 
1984  count -= (scale * char1); // get remainder
1985  }
1986 
1987  // 1 or 2 post-spaces
1988  for ( i = 0; i < numSpaces; i++)
1989  {
1990  CopyDigit ( (_pCharRenderMap + (kDigSpace * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
1991  pFrameBuff += _charWidthBytes;
1992  }
1993  }
1994  }
1995 
1996  return _bInitialized & _bRendered;
1997 }
1998 
1999 void CRP188::CopyDigit (char *pDigit, int digitWidth, int digitHeight, char *pFrameBuff, int fbRowBytes)
2000 {
2001  for (int y = 0; y < digitHeight; y++)
2002  {
2003  char *pSrc = (pDigit + (y * digitWidth));
2004  char *pDst = (pFrameBuff + (y * fbRowBytes));
2005 
2006  memcpy(pDst, pSrc, digitWidth);
2007  }
2008 }
2009 
2010 
2011 string CRP188::GetTimeCodeString(bool bDisplay60_50fpsAs30_25)
2012 {
2013  string result = "";
2014 
2015  int val, char1, char2, trailingChar = kMaxTCChars;
2016 
2017  for (int dig = 0; dig < 4; dig++)
2018  {
2019  // timecode
2020  {
2021  val = _ulVal[3-dig]; // timecode data
2022 
2023  // big ugly gross exception:
2024  // if the timecode format is >= 40 fps BUT we want to display the 2nd frame in the form: "XX:XX:XX:00*", where
2025  // the frame count runs from 0 - 29 (or 24) and '*' means "2nd frame", then we have to schmooze with the data...
2026  if ( dig == 3 // last digit (frames)
2027  && FormatIs60_50fps(_tcFormat) // timecode frame rate > 39 fps
2028  && bDisplay60_50fpsAs30_25 ) // we wanna convert it
2029  {
2030  trailingChar = (val % 2 == 0 ? kDigSpace : kDigAsterisk); // convert ls bit to trailing '*'
2031  val /= 2; // convert 0 - 59 frames to 0 - 29 frames
2032  }
2033 
2034  char1 = val / 10; // tens digit
2035  char2 = val % 10; // units digit
2036  }
2037 
2038  // sanity check
2039  char1 = (char1 < 0 ? 0 : (char1 > kMaxTCChars ? kDigSpace : char1) );
2040  char2 = (char2 < 0 ? 0 : (char2 > kMaxTCChars ? kDigSpace : char2) );
2041 
2042  // "tens" digit
2043  result += '0' + char1;
2044  //CopyDigit ( (_pCharRenderMap + (char1 * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
2045  //pFrameBuff += _charWidthBytes;
2046 
2047  // "ones" digit
2048  result += '0' + char2;
2049  //CopyDigit ( (_pCharRenderMap + (char2 * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
2050  //pFrameBuff += _charWidthBytes;
2051 
2052  // add a colon after each pair (except last)
2053  if (dig < 3)
2054  {
2055  if (dig == 2 && FormatIsDropFrame() )
2056  {
2057  result += ";";
2058  //CopyDigit ( (_pCharRenderMap + (kDigSemicolon * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
2059  }
2060  else
2061  {
2062  result += ":";
2063  //CopyDigit ( (_pCharRenderMap + (kDigColon * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
2064  }
2065  }
2066  }
2067 
2068  // if there is a "trailing character" (sometimes used for Field ID), do it now
2069  if (trailingChar >= 0 && trailingChar < kMaxTCChars)
2070  {
2071  result += '0' + trailingChar;
2072 
2073  //CopyDigit ( (_pCharRenderMap + (trailingChar * charSizeBytes)), _charWidthBytes, _charHeightLines, pFrameBuff, rowBytes);
2074  //pFrameBuff += _charWidthBytes;
2075  }
2076 
2077 
2078  return result;
2079 }
2080 
2081 ostream & operator << (std::ostream & outputStream, const CRP188 & inObj)
2082 {
2083  string result;
2084  inObj.GetRP188Str (result);
2085  outputStream << result;
2086  return outputStream;
2087 }
2088 
2089 
2090 #ifdef MSWindows
2091 #pragma warning(default: 4800)
2092 #endif
CRP188::SubtractFrames
ULWord SubtractFrames(ULWord frameCount)
Definition: ntv2rp188.cpp:1141
BIT_11
#define BIT_11
Definition: ajatypes.h:581
CRP188::AddFrames
ULWord AddFrames(ULWord frameCount)
Definition: ntv2rp188.cpp:1122
CRP188::SetColorFrame
void SetColorFrame(bool bColorFrameFlag)
Definition: ntv2rp188.cpp:744
LWord
int32_t LWord
Definition: ajatypes.h:252
RP188_STRUCT::High
ULWord High
Definition: ntv2publicinterface.h:4086
CRP188::GetOutputFilter
UByte GetOutputFilter() const
Definition: ntv2rp188.cpp:907
NTV2_FBF_ARGB
@ NTV2_FBF_ARGB
See 8-Bit ARGB, RGBA, ABGR Formats.
Definition: ntv2enums.h:212
CRP188::GetRP188Frms
bool GetRP188Frms(ULWord &ulFrms) const
Definition: ntv2rp188.cpp:929
kTCFormat24fps
@ kTCFormat24fps
Definition: ntv2rp188.h:30
NTV2FrameDimensions
Describes the horizontal and vertical size dimensions of a raster, bitmap, frame or image.
Definition: ntv2publicinterface.h:5658
kDigDash
const int kDigDash
Definition: ntv2rp188.cpp:23
NEW_SELECT_RP188_RCVD
#define NEW_SELECT_RP188_RCVD
Definition: ntv2publicinterface.h:4123
CRP188::CopyDigit
void CopyDigit(char *pDigit, int digitWidth, int digitHeight, char *pFrameBuff, int fbRowBytes)
Definition: ntv2rp188.cpp:1999
NTV2_FRAMERATE_1500
@ NTV2_FRAMERATE_1500
15 frames per second
Definition: ntv2enums.h:412
NTV2_FRAMERATE_6000
@ NTV2_FRAMERATE_6000
60 frames per second
Definition: ntv2enums.h:399
NULL
#define NULL
Definition: ntv2caption608types.h:19
CRP188::GetRP188Reg
bool GetRP188Reg(RP188_STRUCT &outRP188) const
Definition: ntv2rp188.cpp:1241
kDigSpace
const int kDigSpace
Definition: ntv2rp188.cpp:24
CRP188::FormatIs60_50fps
bool FormatIs60_50fps(TimecodeFormat format=kTCFormatUnknown) const
Definition: ntv2rp188.cpp:1209
hexChar
static char hexChar[]
Definition: ntv2rp188.cpp:368
NTV2_FRAMERATE_2997
@ NTV2_FRAMERATE_2997
Fractional rate of 30,000 frames per 1,001 seconds.
Definition: ntv2enums.h:403
operator<<
ostream & operator<<(std::ostream &outputStream, const CRP188 &inObj)
Prints the given CRP188's contents into the given output stream.
Definition: ntv2rp188.cpp:2081
CRP188::Init
void Init()
Definition: ntv2rp188.cpp:418
CRP188::GetTimeCodeString
std::string GetTimeCodeString(bool bDisplay60_50fpsAs30_25=false)
Definition: ntv2rp188.cpp:2011
kDigAsterisk
const int kDigAsterisk
Definition: ntv2rp188.cpp:25
CRP188::MaxFramesPerDay
ULWord MaxFramesPerDay(TimecodeFormat format=kTCFormatUnknown) const
Definition: ntv2rp188.cpp:1162
kTCFormat30fpsDF
@ kTCFormat30fpsDF
Definition: ntv2rp188.h:33
CRP188::ConvertTimecode
void ConvertTimecode(ULWord &frameCount, TimecodeFormat format, ULWord hours, ULWord minutes, ULWord seconds, ULWord frames)
Definition: ntv2rp188.cpp:961
BIT_4
#define BIT_4
Definition: ajatypes.h:574
CRP188::operator==
bool operator==(const CRP188 &s)
Definition: ntv2rp188.cpp:428
NTV2FrameBufferFormat
NTV2FrameBufferFormat
Identifies a particular video frame buffer format. See Device Frame Buffer Formats for details.
Definition: ntv2enums.h:207
kTCFormat30fps
@ kTCFormat30fps
Definition: ntv2rp188.h:32
NTV2_FBF_10BIT_DPX
@ NTV2_FBF_10BIT_DPX
See 10-Bit RGB - DPX Format.
Definition: ntv2enums.h:218
TimecodeFormat
TimecodeFormat
Definition: ntv2rp188.h:27
CRP188::GetFrameCount
bool GetFrameCount(ULWord &frameCount)
Definition: ntv2rp188.cpp:953
kTCFormat48fps
@ kTCFormat48fps
Definition: ntv2rp188.h:34
NTV2_FRAMERATE_2500
@ NTV2_FRAMERATE_2500
25 frames per second
Definition: ntv2enums.h:404
NTV2FrameRate
NTV2FrameRate
Identifies a particular video frame rate.
Definition: ntv2enums.h:396
BIT_27
#define BIT_27
Definition: ajatypes.h:597
CRP188::FormatIsPAL
bool FormatIsPAL(TimecodeFormat format=kTCFormatUnknown) const
Definition: ntv2rp188.cpp:1228
kTCFormat60fps
@ kTCFormat60fps
Definition: ntv2rp188.h:36
NTV2_FRAMERATE_4800
@ NTV2_FRAMERATE_4800
48 frames per second
Definition: ntv2enums.h:408
kMaxTCChars
const int kMaxTCChars
Definition: ntv2rp188.cpp:26
BIT_26
#define BIT_26
Definition: ajatypes.h:596
CRP188::~CRP188
virtual ~CRP188()
Definition: ntv2rp188.cpp:411
NTV2_FRAMERATE_2400
@ NTV2_FRAMERATE_2400
24 frames per second
Definition: ntv2enums.h:405
kDefaultFrameCount
const int64_t kDefaultFrameCount
Definition: ntv2rp188.h:49
CRP188::GetRP188Secs
bool GetRP188Secs(ULWord &ulSecs) const
Definition: ntv2rp188.cpp:935
kDigitDotHeight
const int kDigitDotHeight
Definition: ntv2rp188.cpp:31
kTCFormat50fps
@ kTCFormat50fps
Definition: ntv2rp188.h:35
CRP188::GetRP188UserBitsCString
const char * GetRP188UserBitsCString()
Definition: ntv2rp188.cpp:1262
kTCBurnTimecode
@ kTCBurnTimecode
Definition: ntv2rp188.h:42
NTV2_FRAMERATE_2398
@ NTV2_FRAMERATE_2398
Fractional rate of 24,000 frames per 1,001 seconds.
Definition: ntv2enums.h:406
kTCFormat25fps
@ kTCFormat25fps
Definition: ntv2rp188.h:31
ULWord
uint32_t ULWord
Definition: ajatypes.h:253
bcd
static char bcd[]
Definition: ntv2rp188.cpp:367
NTV2_FRAMERATE_1498
@ NTV2_FRAMERATE_1498
Fractional rate of 15,000 frames per 1,001 seconds.
Definition: ntv2enums.h:413
CRP188::SetFieldID
void SetFieldID(ULWord fieldID)
Definition: ntv2rp188.cpp:821
CRP188::SetUserBits
bool SetUserBits(ULWord bits)
Definition: ntv2rp188.cpp:1314
CRP188::SetBinaryGroup
bool SetBinaryGroup(ULWord smpteNum, ULWord bits)
Definition: ntv2rp188.cpp:1284
BIT_10
#define BIT_10
Definition: ajatypes.h:580
kNumBurnInChars
const int kNumBurnInChars
Definition: ntv2rp188.cpp:28
CRP188::SetRP188
void SetRP188(ULWord ulFrms, ULWord ulSecs, ULWord ulMins, ULWord ulHrs, NTV2FrameRate frameRate, const bool bDropFrame=false, const bool bSMPTE372=false)
Definition: ntv2rp188.cpp:587
CRP188::GetRP188Mins
bool GetRP188Mins(ULWord &ulMins) const
Definition: ntv2rp188.cpp:941
NTV2_FBF_8BIT_YCBCR
@ NTV2_FBF_8BIT_YCBCR
See 8-Bit YCbCr Format.
Definition: ntv2enums.h:211
CharMap
static const char CharMap[kMaxTCChars][kDigitDotHeight][kDigitDotWidth]
Definition: ntv2rp188.cpp:34
CRP188::SetBFGBits
void SetBFGBits(bool bBFG0, bool bBFG1, bool bBFG2)
Definition: ntv2rp188.cpp:853
kTCFormat60fpsDF
@ kTCFormat60fpsDF
Definition: ntv2rp188.h:37
CRP188::GetRP188Hrs
bool GetRP188Hrs(ULWord &ulHrs) const
Definition: ntv2rp188.cpp:947
RP188_STRUCT
Definition: ntv2publicinterface.h:4083
CRP188
Definition: ntv2rp188.h:55
kDigSemicolon
const int kDigSemicolon
Definition: ntv2rp188.cpp:22
CRP188::GetFieldID
bool GetFieldID(void)
Definition: ntv2rp188.cpp:841
CRP188::FormatIsDropFrame
bool FormatIsDropFrame(TimecodeFormat format=kTCFormatUnknown) const
Definition: ntv2rp188.cpp:1193
NTV2_FBF_10BIT_YCBCR
@ NTV2_FBF_10BIT_YCBCR
See 10-Bit YCbCr Format.
Definition: ntv2enums.h:210
RP188_STRUCT::DBB
ULWord DBB
Definition: ntv2publicinterface.h:4084
CRP188::CRP188
CRP188()
Definition: ntv2rp188.cpp:374
kDigColon
const int kDigColon
Definition: ntv2rp188.cpp:21
BIT_5
#define BIT_5
Definition: ajatypes.h:575
RP188_STRUCT::Low
ULWord Low
Definition: ntv2publicinterface.h:4085
NTV2_FRAMERATE_5994
@ NTV2_FRAMERATE_5994
Fractional rate of 60,000 frames per 1,001 seconds.
Definition: ntv2enums.h:401
UByte
uint8_t UByte
Definition: ajatypes.h:248
TimecodeBurnMode
TimecodeBurnMode
Definition: ntv2rp188.h:40
CRP188::GetRP188CString
const char * GetRP188CString() const
Definition: ntv2rp188.cpp:924
CRP188::FramesPerSecond
ULWord FramesPerSecond(TimecodeFormat format=kTCFormatUnknown) const
Definition: ntv2rp188.cpp:1370
CRP188::BinaryGroup
ULWord BinaryGroup(ULWord smpteNum)
Definition: ntv2rp188.cpp:1270
std
Definition: json.hpp:5362
NTV2_RP188
This struct replaces the old RP188_STRUCT.
Definition: ntv2publicinterface.h:6760
CRP188::SetOutputFilter
void SetOutputFilter(UByte src)
Definition: ntv2rp188.cpp:901
NTV2_FRAMERATE_UNKNOWN
@ NTV2_FRAMERATE_UNKNOWN
Represents an unknown or invalid frame rate.
Definition: ntv2enums.h:398
CRP188::InitBurnIn
bool InitBurnIn(NTV2FrameBufferFormat frameBufferFormat, NTV2FrameDimensions frameDimensions, LWord percentY=0)
Definition: ntv2rp188.cpp:1564
kDigitDotWidth
const int kDigitDotWidth
Definition: ntv2rp188.cpp:30
kTCBurnUserBits
@ kTCBurnUserBits
Definition: ntv2rp188.h:43
ntv2rp188.h
Declares the CRP188 class. See SMPTE RP188 standard for details.
CRP188::SetDropFrame
void SetDropFrame(bool bDropFrameFlag)
Definition: ntv2rp188.cpp:734
kTCBurnBlank
@ kTCBurnBlank
Definition: ntv2rp188.h:45
CRP188::BurnTC
bool BurnTC(char *pBaseVideoAddress, int rowBytes, TimecodeBurnMode burnMode, int64_t frameCount=kDefaultFrameCount, bool bDisplay60_50fpsAs30_25=false)
Definition: ntv2rp188.cpp:1839
CRP188::GetRP188UserBitsStr
bool GetRP188UserBitsStr(std::string &sRP188UB)
Definition: ntv2rp188.cpp:1253
CRP188::VaricamFrameRate
ULWord VaricamFrameRate(void)
Definition: ntv2rp188.cpp:1361
CRP188::SetVaricamFrameActive
void SetVaricamFrameActive(bool bVaricamActive, ULWord frame)
Definition: ntv2rp188.cpp:754
kTCFormatUnknown
@ kTCFormatUnknown
Definition: ntv2rp188.h:29
NTV2_FRAMERATE_5000
@ NTV2_FRAMERATE_5000
50 frames per second
Definition: ntv2enums.h:407
NTV2_FRAMERATE_4795
@ NTV2_FRAMERATE_4795
Fractional rate of 48,000 frames per 1,001 seconds.
Definition: ntv2enums.h:409
NTV2_FRAMERATE_3000
@ NTV2_FRAMERATE_3000
30 frames per second
Definition: ntv2enums.h:402
BIT
#define BIT(_x_)
Definition: ajatypes.h:561
CRP188::SetVaricamRate
void SetVaricamRate(NTV2FrameRate frameRate)
Definition: ntv2rp188.cpp:774
CRP188::GetSource
UByte GetSource() const
Definition: ntv2rp188.cpp:895
NTV2_FBF_ABGR
@ NTV2_FBF_ABGR
See 8-Bit ARGB, RGBA, ABGR Formats.
Definition: ntv2enums.h:216
CRP188::UDW
ULWord UDW(ULWord smpteUDW)
Definition: ntv2rp188.cpp:1343
CRP188::GetRP188Str
bool GetRP188Str(std::string &sRP188) const
Definition: ntv2rp188.cpp:918
CRP188::ConvertFrameCount
void ConvertFrameCount(ULWord frameCount, TimecodeFormat format, ULWord &hours, ULWord &minutes, ULWord &seconds, ULWord &frames)
Definition: ntv2rp188.cpp:1026
CRP188::DefaultFrameRateForTimecodeFormat
NTV2FrameRate DefaultFrameRateForTimecodeFormat(TimecodeFormat format=kTCFormatUnknown) const
Definition: ntv2rp188.cpp:1399
CRP188::SetSource
void SetSource(UByte src)
Definition: ntv2rp188.cpp:889
CRP188::writeV210Pixel
void writeV210Pixel(char **pBytePtr, int x, int c, int y)
Definition: ntv2rp188.cpp:1802