b3375a7e1d8868bd770b4a982f9c4cfc1bae4321
[vlc.git] / modules / codec / ogt / ogt_parse.c
1 /*****************************************************************************
2  * Philips OGT (SVCD subtitle) packet parser
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: ogt_parse.c,v 1.1 2003/12/28 04:51:52 rocky Exp $
6  *
7  * Author: Rocky Bernstein 
8  *   based on code from: 
9  *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
10  *       Sam Hocevar <sam@zoy.org>
11  *       Laurent Aimar <fenrir@via.ecp.fr>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
26  *****************************************************************************/
27
28 /*****************************************************************************
29  * Preamble
30  *****************************************************************************/
31 #include <vlc/vlc.h>
32 #include <vlc/vout.h>
33 #include <vlc/decoder.h>
34
35 #include "subtitle.h"
36 #include "common.h"
37 #include "render.h"
38 #include "ogt.h"
39
40 /* An image color is a two-bit palette entry: 0..3 */ 
41 typedef uint8_t ogt_color_t;
42
43 /*****************************************************************************
44  * Local prototypes.
45  *****************************************************************************/
46 static int  ParseImage         ( decoder_t *, subpicture_t * );
47
48 /*
49   The format is roughly as follows (everything is big-endian):
50  
51    size     description
52    -------------------------------------------
53    byte     subtitle channel (0..7) in bits 0-3 
54    byte     subtitle packet number of this subtitle image 0-N,
55             if the subtitle packet is complete, the top bit of the byte is 1.
56    u_int16  subtitle image number
57    u_int16  length in bytes of the rest
58    byte     option flags, unknown meaning except bit 3 (0x08) indicates
59             presence of the duration field
60    byte     unknown 
61    u_int32  duration in 1/90000ths of a second (optional), start time
62             is as indicated by the PTS in the PES header
63    u_int32  xpos
64    u_int32  ypos
65    u_int32  width (must be even)
66    u_int32  height (must be even)
67    byte[16] palette, 4 palette entries, each contains values for
68             Y, U, V and transparency, 0 standing for transparent
69    byte     command,
70             cmd>>6==1 indicates shift
71             (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
72    u_int32  shift duration in 1/90000ths of a second
73    u_int16  offset of odd-numbered scanlines - subtitle images are 
74             given in interlace order
75    byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
76             2-bits per palette number
77 */
78
79 /* FIXME: do we really need p_buffer and p? 
80    Can't all of thes _offset's and _lengths's get removed? 
81 */
82 void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
83 {
84   decoder_sys_t *p_sys = p_dec->p_sys;
85   u_int8_t *p = p_buffer;
86   int i;
87   
88   p_sys->i_pts    = p_block->i_pts;
89   p_sys->i_spu_size = GETINT16(p);
90   p_sys->i_options  = *p++;
91   p_sys->i_options2 = *p++;
92   
93   if ( p_sys->i_options & 0x08 ) {
94     p_sys->i_duration = GETINT32(p);
95   } else {
96     /* 0 means display until next subtitle comes in. */
97     p_sys->i_duration = 0;
98   }
99   p_sys->i_x_start= GETINT16(p);
100   p_sys->i_y_start= GETINT16(p);
101   p_sys->i_width  = GETINT16(p);
102   p_sys->i_height = GETINT16(p);
103   
104   for (i=0; i<4; i++) {
105     p_sys->pi_palette[i].s.y = *p++;
106     p_sys->pi_palette[i].s.u = *p++;
107     p_sys->pi_palette[i].s.v = *p++;
108     /* Note alpha is 8 bits. DVD's use only 4 bits. Our rendering routine
109        will use an 8-bit transparancy.
110     */
111     p_sys->pi_palette[i].s.t = *p++;
112   }
113   p_sys->i_cmd = *p++;
114       /* We do not really know this, FIXME */
115   if ( p_sys->i_cmd ) {
116     p_sys->i_cmd_arg = GETINT32(p);
117   }
118
119   /* Actually, this is measured against a different origin, so we have to
120      adjust it */
121   p_sys->second_field_offset = GETINT16(p);
122   p_sys->comp_image_offset = p - p_buffer;
123   p_sys->comp_image_length = p_sys->i_spu_size - p_sys->comp_image_offset;
124   p_sys->metadata_length   = p_sys->comp_image_offset;
125
126   if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) {
127     msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
128              "spu size: %d, duration: %u (d:%d p:%d)",
129              p_sys->i_x_start, p_sys->i_y_start, 
130              p_sys->i_width, p_sys->i_height, 
131              p_sys->i_spu_size, p_sys->i_duration,
132              p_sys->comp_image_length, p_sys->comp_image_offset);
133     
134     for (i=0; i<4; i++) {
135       msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
136                p_sys->pi_palette[i].s.t, p_sys->pi_palette[i].s.y, 
137                p_sys->pi_palette[i].s.u, p_sys->pi_palette[i].s.v );
138     }
139   }
140 }
141
142
143 /*****************************************************************************
144  * ParsePacket: parse an SPU packet and send it to the video output
145  *****************************************************************************
146  * This function parses the SPU packet and, if valid, sends it to the
147  * video output.
148  *****************************************************************************/
149 void 
150 E_(ParsePacket)( decoder_t *p_dec)
151 {
152     decoder_sys_t *p_sys = p_dec->p_sys;
153
154     subpicture_t  *p_spu;
155
156     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
157     
158     /* Allocate the subpicture internal data. */
159     p_spu = vout_CreateSubPicture( p_sys->p_vout, MEMORY_SUBPICTURE );
160     if( p_spu == NULL )
161     {
162         return;
163     }
164
165     /* In ParseImage we expand the run-length encoded color 0's; also
166        we expand pixels and remove the color palette. This should
167        facilitate scaling and antialiasing and speed up rendering.
168     */
169     p_spu->p_sys = malloc( sizeof( subpicture_sys_t ) 
170                            + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
171
172     /* Fill the p_spu structure */
173     vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
174
175     p_spu->pf_render  = VCDSubRender;
176     p_spu->pf_destroy = VCDSubDestroySPU;
177     p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
178
179     p_spu->p_sys->i_x_end        = p_sys->i_x_start + p_sys->i_width - 1;
180     p_spu->p_sys->i_y_end        = p_sys->i_y_start + p_sys->i_height - 1;
181
182     /* FIXME: use aspect ratio for x? */
183     p_spu->i_x        = p_sys->i_x_start * 3 / 4; 
184     p_spu->i_y        = p_sys->i_y_start;
185     p_spu->i_width    = p_sys->i_width;
186     p_spu->i_height   = p_sys->i_height;
187
188     p_spu->i_start    = p_sys->i_pts;
189     p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration * 10);
190     
191     p_spu->p_sys->b_crop  = VLC_FALSE;
192     p_spu->p_sys->i_debug = p_sys->i_debug;
193
194     /* Get display time now. If we do it later, we may miss the PTS. */
195     p_spu->p_sys->i_pts = p_sys->i_pts;
196
197     /* Attach to our input thread */
198     p_spu->p_sys->p_input = vlc_object_find( p_dec,
199                                              VLC_OBJECT_INPUT, FIND_PARENT );
200
201     /* We try to display it */
202     if( ParseImage( p_dec, p_spu ) )
203     {
204         /* There was a parse error, delete the subpicture */
205         vout_DestroySubPicture( p_sys->p_vout, p_spu );
206         return;
207     }
208
209     /* SPU is finished - we can ask the video output to display it */
210     vout_DisplaySubPicture( p_sys->p_vout, p_spu );
211
212 }
213
214 /* Advance pointer to image pointer, update internal i_remaining counter
215    and check that we haven't goine too far  in the image data. */
216 #define advance_color_pointer_byte                                      \
217   p++;                                                                  \
218   i_remaining=4;                                                        \
219   if (p >= maxp) {                                                      \
220     msg_Warn( p_dec,                                                    \
221               "broken subtitle - tried to access beyond end "           \
222               "in image extraction");                                   \
223     return VLC_EGENERIC;                                                \
224   }                                                                     \
225
226 #define advance_color_pointer                                           \
227   i_remaining--;                                                        \
228   if ( i_remaining == 0 ) {                                             \
229     advance_color_pointer_byte;                                         \
230   }                                                                     
231
232 /* Get the next field - either a palette index or a RLE count for
233    color 0.  To do this we use byte image pointer p, and i_remaining
234    which indicates where we are in the byte.
235 */
236 static inline ogt_color_t 
237 ExtractField(uint8_t *p, unsigned int i_remaining) 
238 {
239   return ( ( *p >> 2*(i_remaining-1) ) & 0x3 );
240 }
241
242 /*****************************************************************************
243  * ParseImage: parse the image part of the subtitle
244  *****************************************************************************
245  This part parses the subtitle graphical data and stores it in a more
246  convenient structure for later rendering. 
247
248  The image is encoded using two bits per pixel that select a palette
249  entry except that value 0 starts a limited run-length encoding for
250  color 0.  When 0 is seen, the next two bits encode one less than the
251  number of pixels, so we can encode run lengths from 1 to 4. These get
252  filled with the color in palette entry 0.
253
254  The encoding of each line is padded to a whole number of bytes.  The
255  first field is padded to an even byte length and the complete subtitle
256  is padded to a 4-byte multiple that always include one zero byte at
257  the end.
258
259  However we'll transform this so that that the RLE is expanded and
260  interlacing will also be removed. On output each pixel entry will by 
261  an 8-bit alpha, y, u, and v entry.
262
263  *****************************************************************************/
264 static int 
265 ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
266 {
267     decoder_sys_t *p_sys = p_dec->p_sys;
268
269     unsigned int i_field;  /* The subtitles are interlaced, are we on an
270                               even or odd scanline?  */
271
272     unsigned int i_row;    /* scanline row number */
273     unsigned int i_column; /* scanline column number */
274
275     unsigned int i_width  = p_sys->i_width;
276     unsigned int i_height = p_sys->i_height;
277
278     uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
279
280     uint8_t i_remaining;           /* number of 2-bit pixels remaining 
281                                       in byte of *p */
282     uint8_t i_pending_zero = 0;    /* number of pixels to fill with 
283                                       color zero 0..4 */
284     ogt_color_t i_color;           /* current pixel color: 0..3 */
285     uint8_t *p = p_sys->subtitle_data  + p_sys->comp_image_offset;
286     uint8_t *maxp = p + p_sys->comp_image_length;
287
288     dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d ",
289                i_width, i_height);
290
291     if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)     
292       printf("\n");
293
294     for ( i_field=0; i_field < 2; i_field++ ) {
295       i_remaining = 4;
296       for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
297         for ( i_column=0; i_column<i_width; i_column++ ) {
298
299           if ( i_pending_zero ) {
300             i_pending_zero--;
301             i_color = 0;
302           } else {
303             i_color = ExtractField( p, i_remaining);
304             advance_color_pointer;
305             if ( i_color == 0 ) {
306               i_pending_zero = ExtractField( p, i_remaining );
307               advance_color_pointer;
308               /* Fall through with i_color == 0 to output the first cell */
309             }
310           }
311
312           /* Color is 0-3. */
313           p_dest[i_row*i_width+i_column] = i_color;
314
315           if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)       
316             printf("%1d", i_color);
317
318         }
319
320         if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) 
321           printf("\n");
322
323         if ( i_remaining != 4 ) {
324           /* Lines are padded to complete bytes, ignore padding */
325           advance_color_pointer_byte;
326         }
327       }
328       p = p_sys->subtitle_data + p_sys->comp_image_offset 
329         + p_sys->second_field_offset;
330     }
331
332     /* Dump out image not interlaced... */
333     if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) {
334       uint8_t *p = p_dest;
335       printf("-------------------------------------\n++");
336       for ( i_row=0; i_row < i_height; i_row ++ ) {
337         for ( i_column=0; i_column<i_width; i_column++ ) {
338           printf("%1d", *p++ & 0x03);
339         }
340         printf("\n++");
341       }
342       printf("\n-------------------------------------\n");
343     }
344
345     /* Remove color palette by expanding pixel entries to contain the
346        palette values. We work from the free space at the end to the
347        beginning so we can expand inline.
348     */
349     {
350       int n = (i_height * i_width) - 1;
351       uint8_t    *p_from = p_dest;
352       ogt_yuvt_t *p_to   = (ogt_yuvt_t *) p_dest;
353       
354       for ( ; n >= 0 ; n-- ) {
355         p_to[n] = p_sys->pi_palette[p_from[n]];
356       }
357     }
358
359     /* The video is automatically scaled. However subtitle bitmaps
360        assume a 1:1 aspect ratio. So we need to scale to compensate for
361        or undo the effects of video output scaling. 
362     */
363     /* FIXME do the right scaling depending on vout. It may not be 4:3 */
364     VCDSubScaleX( p_dec, p_spu, 3, 4 );
365
366     return VLC_SUCCESS;
367 }
368