Update to MPlayer SVN rev 31956 and FFmpeg SVN rev 24767.
[vaapi:dantemasons-mplayer.git] / .svn / text-base / sub_cc.c.svn-base
1 /*
2  * decoder for Closed Captions
3  *
4  * This decoder relies on MPlayer's OSD to display subtitles.
5  * Be warned that decoding is somewhat preliminary, though it basically works.
6  *
7  * Most notably, only the text information is decoded as of now, discarding
8  * color, background and position info (see source below).
9  *
10  * uses source from the xine closed captions decoder
11  *
12  * Copyright (C) 2002 Matteo Giani
13  *
14  * This file is part of MPlayer.
15  *
16  * MPlayer is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * MPlayer is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License along
27  * with MPlayer; if not, write to the Free Software Foundation, Inc.,
28  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29  */
30
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34
35 #include "config.h"
36 #include "sub_cc.h"
37
38 #include "subreader.h"
39
40 #include "libvo/video_out.h"
41 #include "libvo/sub.h"
42
43
44 #define CC_MAX_LINE_LENGTH 64
45
46 static char chartbl[128];
47
48 static subtitle buf1,buf2;
49 static subtitle *fb,*bb;
50
51 static unsigned int cursor_pos=0;
52
53 static int initialized=0;
54
55 #define CC_ROLLON 1
56 #define CC_ROLLUP 2
57
58 static int cc_mode=CC_ROLLON;
59 static int cc_lines=4; ///< number of visible rows in CC roll-up mode, not used in CC roll-on mode
60
61 static void display_buffer(subtitle * buf);
62
63 static void build_char_table(void)
64 {
65   int i;
66   /* first the normal ASCII codes */
67   for (i = 0; i < 128; i++)
68     chartbl[i] = (char) i;
69   /* now the special codes */
70   chartbl[0x2a] = 'á';
71   chartbl[0x5c] = 'é';
72   chartbl[0x5e] = 'í';
73   chartbl[0x5f] = 'ó';
74   chartbl[0x60] = 'ú';
75   chartbl[0x7b] = 'ç';
76   chartbl[0x7c] = '÷';
77   chartbl[0x7d] = 'Ñ';
78   chartbl[0x7e] = 'ñ';
79   chartbl[0x7f] = '¤';    /* FIXME: this should be a solid block */
80 }
81
82 static void clear_buffer(subtitle *buf)
83 {
84         int i;
85         buf->lines=0;
86         for(i=0;i<SUB_MAX_TEXT;i++) if(buf->text[i]) {free(buf->text[i]);buf->text[i]=NULL;}
87 }
88
89
90 /**
91  \brief scroll buffer one line up
92  \param buf buffer to scroll
93 */
94 static void scroll_buffer(subtitle* buf)
95 {
96         int i;
97
98         while(buf->lines > cc_lines)
99         {
100                 if(buf->text[0]) free(buf->text[0]);
101
102                 for(i = 0; i < (buf->lines - 1); i++) buf->text[i] = buf->text[i+1];
103
104                 buf->text[buf->lines-1] = NULL;
105                 buf->lines--;
106         }
107 }
108
109
110 void subcc_init(void)
111 {
112         int i;
113         //printf("subcc_init(): initing...\n");
114         build_char_table();
115         for(i=0;i<SUB_MAX_TEXT;i++) {buf1.text[i]=buf2.text[i]=NULL;}
116         buf1.lines=buf2.lines=0;
117         fb=&buf1;
118         bb=&buf2;
119
120         initialized=1;
121 }
122
123 static void append_char(char c)
124 {
125         if(!bb->lines) {bb->lines++; cursor_pos=0;}
126         if(bb->text[bb->lines - 1]==NULL)
127         {
128                 bb->text[bb->lines - 1]=malloc(CC_MAX_LINE_LENGTH);
129                 memset(bb->text[bb->lines - 1],0,CC_MAX_LINE_LENGTH);
130                 cursor_pos=0;
131         }
132
133         if(c=='\n')
134         {
135                 if(cursor_pos>0 && bb->lines < SUB_MAX_TEXT)
136                 {
137                         bb->lines++;cursor_pos=0;
138                         if(cc_mode==CC_ROLLUP){ //Carriage return - scroll buffer one line up
139                                 bb->text[bb->lines - 1]=calloc(1, CC_MAX_LINE_LENGTH);
140                                 scroll_buffer(bb);
141                         }
142                 }
143         }
144         else
145         {
146                 if(cursor_pos==CC_MAX_LINE_LENGTH-1)
147                 {
148                         fprintf(stderr,"CC: append_char() reached CC_MAX_LINE_LENGTH!\n");
149                         return;
150                 }
151                 bb->text[bb->lines - 1][cursor_pos++]=c;
152         }
153         //In CC roll-up mode data should be shown immediately
154         if(cc_mode==CC_ROLLUP) display_buffer(bb);
155 }
156
157
158 static void swap_buffers(void)
159 {
160         subtitle *foo;
161         foo=fb;
162         fb=bb;
163         bb=foo;
164 }
165
166 static void display_buffer(subtitle * buf)
167 {
168         vo_sub=buf;
169         vo_osd_changed(OSDTYPE_SUBTITLE);
170 }
171
172
173 static void cc_decode_EIA608(unsigned short int data)
174 {
175
176   static unsigned short int lastcode=0x0000;
177   unsigned char c1 = data & 0x7f;
178   unsigned char c2 = (data >> 8) & 0x7f;
179
180   if (c1 & 0x60) {              /* normal character, 0x20 <= c1 <= 0x7f */
181            append_char(chartbl[c1]);
182            if(c2 & 0x60)        /*c2 might not be a normal char even if c1 is*/
183                    append_char(chartbl[c2]);
184   }
185   else if (c1 & 0x10)           // control code / special char
186   {
187 //        int channel= (c1 & 0x08) >> 3;
188           c1&=~0x08;
189           if(data!=lastcode)
190           {
191                 if(c2 & 0x40) { /*PAC, Preamble Address Code */
192                         append_char('\n'); /*FIXME properly interpret PACs*/
193                 }
194                 else
195                         switch(c1)
196                         {
197                                 case 0x10:      break; // ext attribute
198                                 case 0x11:
199                                         if((c2 & 0x30)==0x30)
200                                         {
201                                                 //printf("[debug]:Special char (ignored)\n");
202                                                 /*cc_decode_special_char()*/;
203                                         }
204                                         else if (c2 & 0x20)
205                                         {
206                                                 //printf("[debug]: midrow_attr (ignored)\n");
207                                                 /*cc_decode_midrow_attr()*/;
208                                         }
209                                         break;
210                                 case 0x14:
211                                         switch(c2)
212                                         {
213                                                 case 0x00: //CC roll-on mode
214                                                            cc_mode=CC_ROLLON;
215                                                            break;
216                                                 case 0x25: //CC roll-up, 2 rows
217                                                 case 0x26: //CC roll-up, 3 rows
218                                                 case 0x27: //CC roll-up, 4 rows
219                                                            cc_lines=c2-0x23;
220                                                            cc_mode=CC_ROLLUP;
221                                                            break;
222                                                 case 0x2C: display_buffer(NULL); //EDM
223                                                            clear_buffer(fb); break;
224                                                 case 0x2d: append_char('\n');   //carriage return
225                                                            break;
226                                                 case 0x2e: clear_buffer(bb);    //ENM
227                                                            break;
228                                                 case 0x2f: swap_buffers();      //Swap buffers
229                                                            display_buffer(fb);
230                                                            clear_buffer(bb);
231                                                            break;
232                                         }
233                                         break;
234                                 case 0x17:
235                                         if( c2>=0x21 && c2<=0x23) //TAB
236                                         {
237                                                 break;
238                                         }
239                         }
240           }
241   }
242   lastcode=data;
243 }
244
245 static void subcc_decode(unsigned char *inputbuffer, unsigned int inputlength)
246 {
247   /* The first number may denote a channel number. I don't have the
248    * EIA-708 standard, so it is hard to say.
249    * From what I could figure out so far, the general format seems to be:
250    *
251    * repeat
252    *
253    *   0xfe starts 2 byte sequence of unknown purpose. It might denote
254    *        field #2 in line 21 of the VBI. We'll ignore it for the
255    *        time being.
256    *
257    *   0xff starts 2 byte EIA-608 sequence, field #1 in line 21 of the VBI.
258    *        Followed by a 3-code triplet that starts either with 0xff or
259    *        0xfe. In either case, the following triplet needs to be ignored
260    *        for line 21, field 1.
261    *
262    *   0x00 is padding, followed by 2 more 0x00.
263    *
264    *   0x01 always seems to appear at the beginning, always seems to
265    *        be followed by 0xf8, 8-bit number.
266    *        The lower 7 bits of this 8-bit number seem to denote the
267    *        number of code triplets that follow.
268    *        The most significant bit denotes whether the Line 21 field 1
269    *        captioning information is at odd or even triplet offsets from this
270    *        beginning triplet. 1 denotes odd offsets, 0 denotes even offsets.
271    *
272    *        Most captions are encoded with odd offsets, so this is what we
273    *        will assume.
274    *
275    * until end of packet
276    */
277   unsigned char *current = inputbuffer;
278   unsigned int curbytes = 0;
279   unsigned char data1, data2;
280   unsigned char cc_code;
281   int odd_offset = 1;
282
283   while (curbytes < inputlength) {
284     int skip = 2;
285
286     cc_code = *(current);
287
288     if (inputlength - curbytes < 2) {
289 #ifdef LOG_DEBUG
290       fprintf(stderr, "Not enough data for 2-byte CC encoding\n");
291 #endif
292       break;
293     }
294
295     data1 = *(current+1);
296     data2 = *(current + 2);
297     current++; curbytes++;
298
299     switch (cc_code) {
300     case 0xfe:
301       /* expect 2 byte encoding (perhaps CC3, CC4?) */
302       /* ignore for time being */
303       break;
304
305     case 0xff:
306       /* expect EIA-608 CC1/CC2 encoding */
307       // FIXME check parity!
308       // Parity check omitted assuming we are reading from a DVD and therefore
309       // we should encounter no "transmission errors".
310       cc_decode_EIA608(data1 | (data2 << 8));
311       skip = 5;
312       break;
313
314     case 0x00:
315       /* This seems to be just padding */
316       break;
317
318     case 0x01:
319       odd_offset = data2 & 0x80;
320       if (!odd_offset)
321         skip = 5;
322       break;
323
324     default:
325 //#ifdef LOG_DEBUG
326       fprintf(stderr, "Unknown CC encoding: %x\n", cc_code);
327 //#endif
328       break;
329     }
330     current += skip;
331     curbytes += skip;
332   }
333 }
334
335
336 void subcc_process_data(unsigned char *inputdata,unsigned int len)
337 {
338         if(!subcc_enabled) return;
339         if(!initialized) subcc_init();
340
341         subcc_decode(inputdata, len);
342 }