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 
33 #include "cc.h"
34 
35 static int parityok(int n) /* check parity for 2 bytes packed in n */
36 {
37  int mask = 0;
38  int j = 0;
39  int k = 0;
40  for (k = 1, j = 0; j < 7; j++)
41  {
42  if (n & (1 << j))
43  k++;
44  }
45  if ((k & 1) == ((n >> 7) & 1))
46  mask |= 0x00FF;
47  for (k = 1, j = 8; j < 15; j++)
48  {
49  if (n & (1 << j))
50  k++;
51  }
52  if ((k & 1) == ((n >> 15) & 1))
53  mask |= 0xFF00;
54  return mask;
55 }
56 
57 
58 static bool decodebit(const unsigned char *data, int threshold, int scale1)
59 {
60  int sum = 0;
61  for (int i = 0; i < scale1; i++)
62  sum += data[i];
63  return (sum > threshold * scale1);
64 }
65 
66 
67 static int decode(unsigned char *vbiline, int scale0, int scale1)
68 {
69  std::array<int,7> max {};
70  std::array<int,7> min {};
71  std::array<int,7> val {};
72  int sample = 0;
73  int packedbits = 0;
74 
75  max.fill(-1);
76  min.fill(-1);
77  val.fill(-1);
78  int clk = 0;
79  int tmp = 0;
80  int i = 30;
81 
82  while (i < 600 && clk < 7)
83  { /* find and lock all 7 clocks */
84  sample = vbiline[i];
85  if (max[clk] < 0)
86  { /* find maximum value before drop */
87  if (sample > 85 && sample > val[clk])
88  (val[clk] = sample, tmp = i); /* mark new maximum found */
89  else if (val[clk] - sample > 30) /* far enough */
90  (max[clk] = tmp, i = tmp + 10);
91  }
92  else
93  { /* find minimum value after drop */
94  if (sample < 85 && sample < val[clk])
95  (val[clk] = sample, tmp = i); /* mark new minimum found */
96  else if (sample - val[clk] > 30) /* searched far enough */
97  (min[clk++] = tmp, i = tmp + 10);
98  }
99  i++;
100  }
101 
102  min[6] = min[5] - max[5] + max[6];
103 
104  if (clk != 7 || vbiline[max[3]] - vbiline[min[5]] < 45) /* failure to locate clock lead-in */
105  return -1;
106 
107  /* calculate threshold */
108  for (i = 0, sample = 0; i < 7; i++)
109  sample = (sample + vbiline[min[i]] + vbiline[max[i]]) / 3;
110 
111  for (i = min[6]; vbiline[i] < sample; i++);
112 
113  tmp = i + scale0;
114  for (i = 0; i < 16; i++)
115  if (decodebit(&vbiline[tmp + i * scale0], sample, scale1))
116  packedbits |= 1 << i;
117  return packedbits & parityok(packedbits);
118 }
119 
120 #if 0
121 static int webtv_check(char *buf, int len)
122 {
123  unsigned long sum;
124  unsigned long nwords;
125  unsigned short csum = 0;
126  int nbytes = 0;
127 
128  while (buf[0] != '<' && len > 6) //search for the start
129  {
130  buf++;
131  len--;
132  }
133 
134  if (len == 6) //failure to find start
135  return 0;
136 
137  while (nbytes + 6 <= len)
138  {
139  //look for end of object checksum, it's enclosed in []'s and there shouldn't be any [' after
140  if (buf[nbytes] == '[' && buf[nbytes + 5] == ']' && buf[nbytes + 6] != '[')
141  break;
142  else
143  nbytes++;
144  }
145  if (nbytes + 6 > len) //failure to find end
146  return 0;
147 
148  nwords = nbytes >> 1;
149  sum = 0;
150 
151  //add up all two byte words
152  while (nwords-- > 0)
153  {
154  sum += *buf++ << 8;
155  sum += *buf++;
156  }
157  if (nbytes & 1)
158  {
159  sum += *buf << 8;
160  }
161  csum = (unsigned short) (sum >> 16);
162  while (csum != 0)
163  {
164  sum = csum + (sum & 0xffff);
165  csum = (unsigned short) (sum >> 16);
166  }
167 
168  std::array<char,9> temp {};
169  sprintf(temp.data(), "%04X\n", (int) ~sum & 0xffff);
170  buf++;
171  if (!strncmp(buf, temp.data(), 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 nullptr;
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 nullptr;
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 }
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:237
cc::scale1
int scale1
Definition: cc.h:19
cc
Definition: cc.h:9
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:43
tmp
static guint32 * tmp
Definition: goom_core.cpp:26
decode
static int decode(unsigned char *vbiline, int scale0, int scale1)
Definition: cc.cpp:67
parityok
static int parityok(int n)
Definition: cc.cpp:35
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:58
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:207