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 <cstdlib>
24 #include <cstdarg>
25 #include <unistd.h>
26 #include <cstring>
27 #include <cctype>
28 #include <cerrno>
29 #include <fcntl.h>
30 #include <sys/types.h>
31 #if HAVE_GETOPT_H
32 # include <getopt.h>
33 #endif
34 
35 #include "cc.h"
36 
37 static int parityok(int n) /* check parity for 2 bytes packed in n */
38 {
39  int mask = 0;
40  int j = 0;
41  int k = 0;
42  for (k = 1, j = 0; j < 7; j++)
43  {
44  if (n & (1 << j))
45  k++;
46  }
47  if ((k & 1) == ((n >> 7) & 1))
48  mask |= 0x00FF;
49  for (k = 1, j = 8; j < 15; j++)
50  {
51  if (n & (1 << j))
52  k++;
53  }
54  if ((k & 1) == ((n >> 15) & 1))
55  mask |= 0xFF00;
56  return mask;
57 }
58 
59 
60 static bool decodebit(const unsigned char *data, int threshold, int scale1)
61 {
62  int sum = 0;
63  for (int i = 0; i < scale1; i++)
64  sum += data[i];
65  return (sum > threshold * scale1);
66 }
67 
68 
69 static int decode(unsigned char *vbiline, int scale0, int scale1)
70 {
71  int max[7];
72  int min[7];
73  int val[7];
74  int sample = 0;
75  int packedbits = 0;
76 
77  for (int clk = 0; clk < 7; clk++)
78  max[clk] = min[clk] = val[clk] = -1;
79  int clk = 0;
80  int tmp = 0;
81  int i = 30;
82 
83  while (i < 600 && clk < 7)
84  { /* find and lock all 7 clocks */
85  sample = vbiline[i];
86  if (max[clk] < 0)
87  { /* find maximum value before drop */
88  if (sample > 85 && sample > val[clk])
89  (val[clk] = sample, tmp = i); /* mark new maximum found */
90  else if (val[clk] - sample > 30) /* far enough */
91  (max[clk] = tmp, i = tmp + 10);
92  }
93  else
94  { /* find minimum value after drop */
95  if (sample < 85 && sample < val[clk])
96  (val[clk] = sample, tmp = i); /* mark new minimum found */
97  else if (sample - val[clk] > 30) /* searched far enough */
98  (min[clk++] = tmp, i = tmp + 10);
99  }
100  i++;
101  }
102 
103  min[6] = min[5] - max[5] + max[6];
104 
105  if (clk != 7 || vbiline[max[3]] - vbiline[min[5]] < 45) /* failure to locate clock lead-in */
106  return -1;
107 
108  /* calculate threshold */
109  for (i = 0, sample = 0; i < 7; i++)
110  sample = (sample + vbiline[min[i]] + vbiline[max[i]]) / 3;
111 
112  for (i = min[6]; vbiline[i] < sample; i++);
113 
114  tmp = i + scale0;
115  for (i = 0; i < 16; i++)
116  if (decodebit(&vbiline[tmp + i * scale0], sample, scale1))
117  packedbits |= 1 << i;
118  return packedbits & parityok(packedbits);
119 }
120 
121 #if 0
122 static int webtv_check(char *buf, int len)
123 {
124  unsigned long sum;
125  unsigned long nwords;
126  unsigned short csum = 0;
127  char temp[9];
128  int nbytes = 0;
129 
130  while (buf[0] != '<' && len > 6) //search for the start
131  {
132  buf++;
133  len--;
134  }
135 
136  if (len == 6) //failure to find start
137  return 0;
138 
139  while (nbytes + 6 <= len)
140  {
141  //look for end of object checksum, it's enclosed in []'s and there shouldn't be any [' after
142  if (buf[nbytes] == '[' && buf[nbytes + 5] == ']' && buf[nbytes + 6] != '[')
143  break;
144  else
145  nbytes++;
146  }
147  if (nbytes + 6 > len) //failure to find end
148  return 0;
149 
150  nwords = nbytes >> 1;
151  sum = 0;
152 
153  //add up all two byte words
154  while (nwords-- > 0)
155  {
156  sum += *buf++ << 8;
157  sum += *buf++;
158  }
159  if (nbytes & 1)
160  {
161  sum += *buf << 8;
162  }
163  csum = (unsigned short) (sum >> 16);
164  while (csum != 0)
165  {
166  sum = csum + (sum & 0xffff);
167  csum = (unsigned short) (sum >> 16);
168  }
169  sprintf(temp, "%04X\n", (int) ~sum & 0xffff);
170  buf++;
171  if (!strncmp(buf, temp, 4))
172  {
173  buf[5] = 0;
174  printf("\33[35mWEBTV: %s\33[0m\n", buf - nbytes - 1);
175  fflush(stdout);
176  }
177  return 0;
178 }
179 #endif
180 
181 #if 0
182 // don't use this, blocking IO prevents shuttown of the NVP
183 struct cc *cc_open(const char *vbi_name)
184 {
185  struct cc *cc;
186 
187  if (!(cc = new struct cc))
188  {
189  printf("out of memory\n");
190  return 0;
191  }
192 
193  if ((cc->fd = open(vbi_name, O_RDONLY)) == -1)
194  {
195  printf("cannot open vbi device\n");
196  free(cc);
197  return 0;
198  }
199 
200  cc->code1 = -1;
201  cc->code2 = -1;
202 
203  return cc;
204 }
205 #endif
206 
207 void cc_close(struct cc *cc)
208 {
209  close(cc->fd);
210  delete cc;
211 }
212 
213 // returns:
214 // 0 = no new data yet
215 // 1 = new channel 1 data present in outtext
216 // 2 = new channel 2 data present in outtext
217 // -1 = invalid cc data, reset all outtext
218 // -2 = readerror
219 #if 0
220 // don't use this, blocking IO prevents shuttown of the NVP
221 void cc_handler(struct cc *cc)
222 {
224  {
225  printf("Can't read vbi data\n");
226  cc->code1 = -2;
227  cc->code2 = -2;
228  }
229  else
230  {
231  cc->code1 = decode((unsigned char *)(cc->buffer + (2048 * 11)));
232  cc->code2 = decode((unsigned char *)(cc->buffer + (2048 * 27)));
233  }
234 }
235 #endif
236 
237 void cc_decode(struct cc *cc)
238 {
239  int spl = cc->samples_per_line;
240  int sl = cc->start_line;
241  int l21_f1 = spl * (21 - sl);
242  int l21_f2 = spl * (cc->line_count + 21 - sl);
243  cc->code1 = decode((unsigned char *)(cc->buffer + l21_f1), cc->scale0, cc->scale1);
244  cc->code2 = decode((unsigned char *)(cc->buffer + l21_f2), cc->scale0, cc->scale1);
245 }
int scale1
Definition: cc.h:23
static int parityok(int n)
Definition: cc.cpp:37
void cc_handler(struct cc *cc)
Definition: cc.h:13
static int decode(unsigned char *vbiline, int scale0, int scale1)
Definition: cc.cpp:69
int start_line
Definition: cc.h:21
char buffer[CC_VBIBUFSIZE]
Definition: cc.h:16
void cc_decode(struct cc *cc)
Definition: cc.cpp:237
#define CC_VBIBUFSIZE
Definition: cc.h:8
static bool decodebit(const unsigned char *data, int threshold, int scale1)
Definition: cc.cpp:60
int fd
Definition: cc.h:15
static guint32 * tmp
Definition: goom_core.c:35
int code2
Definition: cc.h:18
def read(device=None, features=[])
Definition: disc.py:35
#define close
Definition: compat.h:16
int line_count
Definition: cc.h:22
void cc_close(struct cc *cc)
Definition: cc.cpp:207
int scale0
Definition: cc.h:23
struct cc * cc_open(const char *vbi_name)
int samples_per_line
Definition: cc.h:20
int code1
Definition: cc.h:17