MythTV  master
cc.cpp
Go to the documentation of this file.
1 /* cc.c -- closed caption decoder
2  * Robert Kulagowski (rkulagowski@thrupoint.net) 2003-01-02
3  * further adopted for MythTV by Erik Arendse
4  * essentially, a stripped copy of ntsc-cc.c from xawtv project
5  * Mike Baker (mbm@linux.com)
6  * (based on code by timecop@japan.co.jp)
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 #include <array>
24 #include <cstdlib>
25 #include <cstdarg>
26 #include <unistd.h>
27 #include <cstring>
28 #include <cctype>
29 #include <cerrno>
30 #include <fcntl.h>
31 #include <sys/types.h>
32 #if HAVE_GETOPT_H
33 # include <getopt.h>
34 #endif
35 
36 #include "cc.h"
37 
38 static int parityok(int n) /* check parity for 2 bytes packed in n */
39 {
40  int mask = 0;
41  int j = 0;
42  int k = 0;
43  for (k = 1, j = 0; j < 7; j++)
44  {
45  if (n & (1 << j))
46  k++;
47  }
48  if ((k & 1) == ((n >> 7) & 1))
49  mask |= 0x00FF;
50  for (k = 1, j = 8; j < 15; j++)
51  {
52  if (n & (1 << j))
53  k++;
54  }
55  if ((k & 1) == ((n >> 15) & 1))
56  mask |= 0xFF00;
57  return mask;
58 }
59 
60 
61 static bool decodebit(const unsigned char *data, int threshold, int scale1)
62 {
63  int sum = 0;
64  for (int i = 0; i < scale1; i++)
65  sum += data[i];
66  return (sum > threshold * scale1);
67 }
68 
69 
70 static int decode(unsigned char *vbiline, int scale0, int scale1)
71 {
72  std::array<int,7> max {};
73  std::array<int,7> min {};
74  std::array<int,7> val {};
75  int sample = 0;
76  int packedbits = 0;
77 
78  max.fill(-1);
79  min.fill(-1);
80  val.fill(-1);
81  int clk = 0;
82  int tmp = 0;
83  int i = 30;
84 
85  while (i < 600 && clk < 7)
86  { /* find and lock all 7 clocks */
87  sample = vbiline[i];
88  if (max[clk] < 0)
89  { /* find maximum value before drop */
90  if (sample > 85 && sample > val[clk])
91  (val[clk] = sample, tmp = i); /* mark new maximum found */
92  else if (val[clk] - sample > 30) /* far enough */
93  (max[clk] = tmp, i = tmp + 10);
94  }
95  else
96  { /* find minimum value after drop */
97  if (sample < 85 && sample < val[clk])
98  (val[clk] = sample, tmp = i); /* mark new minimum found */
99  else if (sample - val[clk] > 30) /* searched far enough */
100  (min[clk++] = tmp, i = tmp + 10);
101  }
102  i++;
103  }
104 
105  min[6] = min[5] - max[5] + max[6];
106 
107  if (clk != 7 || vbiline[max[3]] - vbiline[min[5]] < 45) /* failure to locate clock lead-in */
108  return -1;
109 
110  /* calculate threshold */
111  for (i = 0, sample = 0; i < 7; i++)
112  sample = (sample + vbiline[min[i]] + vbiline[max[i]]) / 3;
113 
114  for (i = min[6]; vbiline[i] < sample; i++);
115 
116  tmp = i + scale0;
117  for (i = 0; i < 16; i++)
118  if (decodebit(&vbiline[tmp + i * scale0], sample, scale1))
119  packedbits |= 1 << i;
120  return packedbits & parityok(packedbits);
121 }
122 
123 #if 0
124 static int webtv_check(char *buf, int len)
125 {
126  unsigned long sum;
127  unsigned long nwords;
128  unsigned short csum = 0;
129  int nbytes = 0;
130 
131  while (buf[0] != '<' && len > 6) //search for the start
132  {
133  buf++;
134  len--;
135  }
136 
137  if (len == 6) //failure to find start
138  return 0;
139 
140  while (nbytes + 6 <= len)
141  {
142  //look for end of object checksum, it's enclosed in []'s and there shouldn't be any [' after
143  if (buf[nbytes] == '[' && buf[nbytes + 5] == ']' && buf[nbytes + 6] != '[')
144  break;
145  else
146  nbytes++;
147  }
148  if (nbytes + 6 > len) //failure to find end
149  return 0;
150 
151  nwords = nbytes >> 1;
152  sum = 0;
153 
154  //add up all two byte words
155  while (nwords-- > 0)
156  {
157  sum += *buf++ << 8;
158  sum += *buf++;
159  }
160  if (nbytes & 1)
161  {
162  sum += *buf << 8;
163  }
164  csum = (unsigned short) (sum >> 16);
165  while (csum != 0)
166  {
167  sum = csum + (sum & 0xffff);
168  csum = (unsigned short) (sum >> 16);
169  }
170 
171  std::array<char,9> temp {};
172  sprintf(temp.data(), "%04X\n", (int) ~sum & 0xffff);
173  buf++;
174  if (!strncmp(buf, temp.data(), 4))
175  {
176  buf[5] = 0;
177  printf("\33[35mWEBTV: %s\33[0m\n", buf - nbytes - 1);
178  fflush(stdout);
179  }
180  return 0;
181 }
182 #endif
183 
184 #if 0
185 // don't use this, blocking IO prevents shuttown of the NVP
186 struct cc *cc_open(const char *vbi_name)
187 {
188  struct cc *cc;
189 
190  if (!(cc = new struct cc))
191  {
192  printf("out of memory\n");
193  return nullptr;
194  }
195 
196  if ((cc->fd = open(vbi_name, O_RDONLY)) == -1)
197  {
198  printf("cannot open vbi device\n");
199  free(cc);
200  return nullptr;
201  }
202 
203  cc->code1 = -1;
204  cc->code2 = -1;
205 
206  return cc;
207 }
208 #endif
209 
210 void cc_close(struct cc *cc)
211 {
212  close(cc->fd);
213  delete cc;
214 }
215 
216 // returns:
217 // 0 = no new data yet
218 // 1 = new channel 1 data present in outtext
219 // 2 = new channel 2 data present in outtext
220 // -1 = invalid cc data, reset all outtext
221 // -2 = readerror
222 #if 0
223 // don't use this, blocking IO prevents shuttown of the NVP
224 void cc_handler(struct cc *cc)
225 {
227  {
228  printf("Can't read vbi data\n");
229  cc->code1 = -2;
230  cc->code2 = -2;
231  }
232  else
233  {
234  cc->code1 = decode((unsigned char *)(cc->buffer + (2048 * 11)));
235  cc->code2 = decode((unsigned char *)(cc->buffer + (2048 * 27)));
236  }
237 }
238 #endif
239 
240 void cc_decode(struct cc *cc)
241 {
242  int spl = cc->samples_per_line;
243  int sl = cc->start_line;
244  int l21_f1 = spl * (21 - sl);
245  int l21_f2 = spl * (cc->line_count + 21 - sl);
246  cc->code1 = decode((unsigned char *)(cc->buffer + l21_f1), cc->scale0, cc->scale1);
247  cc->code2 = decode((unsigned char *)(cc->buffer + l21_f2), cc->scale0, cc->scale1);
248 }
CC_VBIBUFSIZE
#define CC_VBIBUFSIZE
Definition: cc.h:4
cc::code2
int code2
Definition: cc.h:14
discid.disc.read
def read(device=None, features=[])
Definition: disc.py:35
cc_decode
void cc_decode(struct cc *cc)
Definition: cc.cpp:240
cc::scale1
int scale1
Definition: cc.h:19
cc
Definition: cc.h:10
cc::start_line
int start_line
Definition: cc.h:17
cc::buffer
char buffer[CC_VBIBUFSIZE]
Definition: cc.h:12
close
#define close
Definition: compat.h:16
tmp
static guint32 * tmp
Definition: goom_core.cpp:31
decode
static int decode(unsigned char *vbiline, int scale0, int scale1)
Definition: cc.cpp:70
parityok
static int parityok(int n)
Definition: cc.cpp:38
cc::samples_per_line
int samples_per_line
Definition: cc.h:16
hardwareprofile.distros.mythtv_data.main.stdout
stdout
Definition: main.py:87
cc::fd
int fd
Definition: cc.h:11
cc::line_count
int line_count
Definition: cc.h:18
cc.h
cc::code1
int code1
Definition: cc.h:13
cc::scale0
int scale0
Definition: cc.h:19
decodebit
static bool decodebit(const unsigned char *data, int threshold, int scale1)
Definition: cc.cpp:61
cc_handler
void cc_handler(struct cc *cc)
cc_open
struct cc * cc_open(const char *vbi_name)
cc_close
void cc_close(struct cc *cc)
Definition: cc.cpp:210