]> git.vomp.tv Git - vompclient.git/blob - wwss.cc
dvbsubtitles fixup part 2
[vompclient.git] / wwss.cc
1 /*
2     Copyright 2006 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "wwss.h"
22
23 #include "colour.h"
24 #include "video.h"
25
26 Wwss::Wwss()
27 {
28   format = Video::NTSC;
29 }
30
31 Wwss::~Wwss()
32 {
33 }
34
35 void Wwss::setFormat(UCHAR tformat)
36 {
37   format = tformat;
38 }
39
40 UINT Wwss::gcd(UINT a, UINT b)
41 {
42   UINT t;
43   while (b != 0)
44   {
45     t = b;
46     b = a % b;
47     a = t;
48   }
49   return a;
50 }
51
52 UINT Wwss::lcm(UINT a, UINT b)
53 {
54   return (a / gcd(a, b)) * b;
55 }
56
57 void Wwss::setWide(bool twide)
58 {
59   wide = twide;
60 }
61
62 void Wwss::draw()
63 {
64   if (format == Video::PAL) drawPAL();
65   //  else if (format == Video::NTSC) drawNTSC();
66 }
67
68 void Wwss::drawPAL()
69 {
70   // The aspect43 and aspect169 codes are not what they should be according to the docs, but these are what work...
71   // (1 = 111000, = 0 000111)
72   static UCHAR runIn[]     = {1,1,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1};                       // 29 pos 0
73   static UCHAR startCode[] = {0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0,0,0,1,1,1,1,1};                                 // 24 pos 29
74   static UCHAR aspect43[]  = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,1,1,0,0,0}; // = 0001   4:3 full frame      // 24 pos 53
75   static UCHAR aspect169[] = {1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1}; // = 1110   16:9 anamorphic     // 24 pos 53
76   static UCHAR theRest[]   = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,                                  // 60 pos 77
77                               0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1,
78                               0,0,0,1,1,1,0,0,0,1,1,1};
79   /*
80   Real PAL pixel frequency: 13.5 MHz
81   WSS element frequency: 5 MHz
82   = 2.7 pal pixels per wss element
83   * 137 wss elements = 369.9 pal pixels (total code width) (round to 370..)
84
85   There is also a 11us gap at the start of the pal raster, but since I don't really have any
86   idea where our 720 pixels start in the raster I can't calculate an offset.
87
88   PAL line 23 seems to be MVP line 6.
89   */
90
91   const UINT   Ns = 137;           // Num pix src
92   const UINT   Nd = 370;           // Num pix dst         359->395 does something. not the right thing, but something.
93   UINT         Nl = lcm(Ns, Nd);   // Num pix in lcm
94   UINT         Ss = Nl / Ns;       // Source split (how many lcm px = 1 src px)
95   UINT         Sd = Nl / Nd;       // Dst split
96   UCHAR src[Ns];
97
98   memcpy(&src[0], runIn, 29);
99   memcpy(&src[29], startCode, 24);
100   if (wide) memcpy(&src[53], aspect169, 24);
101   else      memcpy(&src[53], aspect43, 24);
102   memcpy(&src[77], theRest, 60);
103
104   float dst[Nd];
105   UINT lcmpxbase = 0;
106
107   for(UINT t = 0; t < Nd; t++) // for every destination pixel
108   {
109     dst[t] = 0;
110     for(UINT lcmpx = lcmpxbase; lcmpx < (lcmpxbase + Sd); lcmpx++)
111     {
112       if (src[lcmpx / Ss]) dst[t] += (float)1/Sd;
113     }
114     lcmpxbase += Sd;
115   }
116
117   Colour c;
118   UINT value;
119
120   Surface* mysurface = getSurface();
121   for(UINT q = 0; q < Nd; q++)
122   {
123     value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value
124     c.set(value, value, value);
125     mysurface->drawPixel(q, 6, c);
126   }
127 }
128
129 void Wwss::drawNTSC()
130 {
131   /*
132   static UCHAR startCode[] = {1,0,0,0,0,0,0};
133   static UCHAR aspect43[]  = {0};
134   static UCHAR aspect169[] = {1};
135   static UCHAR theRest[]   = {0,0,0,0,0,0,0,0};
136   static UCHAR crc43[]     = {0,0,0,0,0,0};
137   static UCHAR crc169[]    = {0,0,1,1,0,0};
138   */
139   /*
140   Real NTSC pixel frequency: 13.5 MHz
141   WSS bit frequency: 447.443125 kHz
142   = 30.1714 NTSC pixels per wss bit
143   * 22 wss bits = 663.7715 NTSC pixels (total code width) (round to 664..)
144
145   There is also a 11.2us gap at the start of the pal raster, but since I don't really have any
146   idea where our 720 pixels start in the raster I can't calculate an offset.
147
148   PAL line 23 seems to be MVP line 6.
149   */
150
151   const UINT   Ns = 22;            // Num pix src
152   const UINT   Nd = 664;           // Num pix dst
153   //  const UINT   Nd = 518;           // Num pix dst
154   UINT         Nl = lcm(Ns, Nd);   // Num pix in lcm
155   UINT         Ss = Nl / Ns;       // Source split (how many lcm px = 1 src px)
156   UINT         Sd = Nl / Nd;       // Dst split
157   //  UCHAR src[Ns];
158
159   /*
160   memcpy(&src[0], startCode, 7);
161   if (wide) memcpy(&src[7], aspect169, 1);
162   else      memcpy(&src[7], aspect43, 1);
163   memcpy(&src[8], theRest, 8);
164   if (wide) memcpy(&src[16], crc169, 6);
165   else      memcpy(&src[16], crc43, 6);
166   */
167
168   static UCHAR src[22] = {1,0, 0,0,0,0,1,1, 0,0,0,0, 0,0,0,0, 0,0,1,0,0,1 };
169
170
171   float dst[Nd];
172   UINT lcmpxbase = 0;
173
174   for(UINT t = 0; t < Nd; t++) // for every destination pixel
175   {
176     dst[t] = 0;
177     for(UINT lcmpx = lcmpxbase; lcmpx < (lcmpxbase + Sd); lcmpx++)
178     {
179       if (src[lcmpx / Ss]) dst[t] += (float)1/Sd;
180     }
181     lcmpxbase += Sd;
182   }
183
184   Colour c;
185   UINT value;
186
187   // This one is the real one
188   /*
189   Surface* mysurface = getSurface();
190   for(UINT q = 0; q < Nd; q++)
191   {
192     value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value
193     c.set(value, value, value);
194     mysurface->drawPixel(q, 6, c);
195   }
196   */
197
198   // This one is testing active
199   Surface* mysurface = getSurface();
200   for(int yy = 0; yy < 100; yy++)
201   {
202     for(UINT q = 0; q < Nd; q++)
203     {
204       value = (UINT)(dst[q] * 182); // Apparently this is a better number than 255 for the colour value
205       c.set(value, value, value);
206       mysurface->drawPixel(q+0, yy, c);
207     }
208   }
209 }
210
211 /*
212 x6 + x + 1
213
214 1x6 + 0x5 + 0x4 + 0x3 + 0x2 + 1x1 + 1x0
215 =
216 1      0     0     0     0     1     1
217 =
218 1000011
219 key width = 6
220
221 static UCHAR startCode[] = {1,0};
222 static UCHAR aspect43[]  = {0,0};
223 static UCHAR aspect169[] = {1,0};
224 static UCHAR theRest[]   = {0,0,0,0,0,0,0,0,0,0,0,0};
225 static UCHAR crc43[]     = {0,0,0,0,0,0};
226 static UCHAR crc169[]    = {0,0,1,0,0,1};
227
228 Message 4:3
229
230 1000000000000000
231
232 Message 4:3 augmented
233
234 1000000000000000000000
235
236 Key
237
238 1000011
239
240
241 Ho ho, polynomial long division. Yeeeeaaahhh I remember
242 doing *that*. Of course I do. If you know of a faster,
243 easier, more reliable way of doing this, please let me know.
244
245
246                  100
247          ________________________
248 1000011  ) 1000000000000000000000
249            1000011
250            -------
251             0000110
252             0000000
253             -------
254              0001100
255
256
257
258
259
260
261 Message 16:9
262
263 1010000000000000
264
265 Message 4:3 augmented
266
267 1010000000000000000000
268
269 Key
270
271 1000011
272
273                  1010011110100011
274          ________________________
275 1000011  ) 1010000000000000000000
276            1000011
277             -------
278             0100110
279             0000000
280              -------
281              1001100
282              1000011
283               -------
284               0011110
285               0000000
286                -------
287                0111100
288                0000000
289                 -------
290                 1111000
291                 1000011
292                  -------
293                  1110110
294                  1000011
295                   -------
296                   1101010
297                   1000011
298                    -------
299                    1010010
300                    1000011
301                     -------
302                     0100010
303                     0000000
304                      -------
305                      1000100
306                      1000011
307                       -------
308                       0001110
309                       0000000
310                        -------
311                        0011100
312                        0000000
313                         -------
314                         0111000
315                         0000000
316                          -------
317                          1110000
318                          1000011
319                           -------
320                           1100110
321                           1000011
322                           -------
323                            100101
324 */