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