Work towards handling all planes in subtites, generalizing for CVD, and
[vlc.git] / modules / codec / ogt / parse.c
1 /*****************************************************************************
2  * parse.c: Philips OGT (SVCD subtitle) packet parser
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: parse.c,v 1.3 2003/12/28 02:01:11 rocky Exp $
6  *
7  * Authors: 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 "render.h"
37 #include "ogt.h"
38
39 /* An image color is a two-bit palette entry: 0..3 */ 
40 typedef uint8_t ogt_color_t;
41
42 /*****************************************************************************
43  * Local prototypes.
44  *****************************************************************************/
45 static int  ParseImage         ( decoder_t *, subpicture_t * );
46
47 static void DestroySPU       ( subpicture_t * );
48
49 static void UpdateSPU        ( subpicture_t *, vlc_object_t * );
50 static int  CropCallback     ( vlc_object_t *, char const *,
51                                vlc_value_t, vlc_value_t, void * );
52
53 /*
54   The format is roughly as follows (everything is big-endian):
55  
56    size     description
57    -------------------------------------------
58    byte     subtitle channel (0..7) in bits 0-3 
59    byte     subtitle packet number of this subtitle image 0-N,
60             if the subtitle packet is complete, the top bit of the byte is 1.
61    u_int16  subtitle image number
62    u_int16  length in bytes of the rest
63    byte     option flags, unknown meaning except bit 3 (0x08) indicates
64             presence of the duration field
65    byte     unknown 
66    u_int32  duration in 1/90000ths of a second (optional), start time
67             is as indicated by the PTS in the PES header
68    u_int32  xpos
69    u_int32  ypos
70    u_int32  width (must be even)
71    u_int32  height (must be even)
72    byte[16] palette, 4 palette entries, each contains values for
73             Y, U, V and transparency, 0 standing for transparent
74    byte     command,
75             cmd>>6==1 indicates shift
76             (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
77    u_int32  shift duration in 1/90000ths of a second
78    u_int16  offset of odd-numbered scanlines - subtitle images are 
79             given in interlace order
80    byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
81             2-bits per palette number
82 */
83
84 /* FIXME: do we really need p_buffer and p? 
85    Can't all of thes _offset's and _lengths's get removed? 
86 */
87 void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
88 {
89   decoder_sys_t *p_sys = p_dec->p_sys;
90   u_int8_t *p = p_buffer;
91   int i;
92   
93   p_sys->i_pts    = p_block->i_pts;
94   p_sys->i_spu_size = GETINT16(p);
95   p_sys->i_options  = *p++;
96   p_sys->i_options2 = *p++;
97   
98   if ( p_sys->i_options & 0x08 ) {
99     p_sys->i_duration = GETINT32(p);
100   } else {
101     /* 0 means display until next subtitle comes in. */
102     p_sys->i_duration = 0;
103   }
104   p_sys->i_x_start= GETINT16(p);
105   p_sys->i_y_start= GETINT16(p);
106   p_sys->i_width  = GETINT16(p);
107   p_sys->i_height = GETINT16(p);
108   
109   for (i=0; i<4; i++) {
110     p_sys->pi_palette[i].s.y = *p++;
111     p_sys->pi_palette[i].s.u = *p++;
112     p_sys->pi_palette[i].s.v = *p++;
113     /* Note alpha is 8 bits. DVD's use only 4 bits. Our rendering routine
114        will use an 8-bit transparancy.
115     */
116     p_sys->pi_palette[i].s.t = *p++;
117   }
118   p_sys->i_cmd = *p++;
119       /* We do not really know this, FIXME */
120   if ( p_sys->i_cmd ) {
121     p_sys->i_cmd_arg = GETINT32(p);
122   }
123
124   /* Actually, this is measured against a different origin, so we have to
125      adjust it */
126   p_sys->second_field_offset = GETINT16(p);
127   p_sys->comp_image_offset = p - p_buffer;
128   p_sys->comp_image_length = p_sys->i_spu_size - p_sys->comp_image_offset;
129   p_sys->metadata_length   = p_sys->comp_image_offset;
130
131   if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) {
132     msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
133              "spu size: %d, duration: %u (d:%d p:%d)",
134              p_sys->i_x_start, p_sys->i_y_start, 
135              p_sys->i_width, p_sys->i_height, 
136              p_sys->i_spu_size, p_sys->i_duration,
137              p_sys->comp_image_length, p_sys->comp_image_offset);
138     
139     for (i=0; i<4; i++) {
140       msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
141                p_sys->pi_palette[i].s.t, p_sys->pi_palette[i].s.y, 
142                p_sys->pi_palette[i].s.u, p_sys->pi_palette[i].s.v );
143     }
144   }
145 }
146
147
148 /*****************************************************************************
149  * ParsePacket: parse an SPU packet and send it to the video output
150  *****************************************************************************
151  * This function parses the SPU packet and, if valid, sends it to the
152  * video output.
153  *****************************************************************************/
154 void 
155 E_(ParsePacket)( decoder_t *p_dec)
156 {
157     decoder_sys_t *p_sys = p_dec->p_sys;
158
159     subpicture_t  *p_spu;
160
161     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
162     
163     /* Allocate the subpicture internal data. */
164     p_spu = vout_CreateSubPicture( p_sys->p_vout, MEMORY_SUBPICTURE );
165     if( p_spu == NULL )
166     {
167         return;
168     }
169
170     /* In ParseImage we expand the run-length encoded color 0's; also
171        we expand pixels and remove the color palette. This should
172        facilitate scaling and antialiasing and speed up rendering.
173     */
174     p_spu->p_sys = malloc( sizeof( subpicture_sys_t ) 
175                            + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
176
177     /* Fill the p_spu structure */
178     vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
179
180     p_spu->pf_render  = VCDRenderSPU;
181     p_spu->pf_destroy = DestroySPU;
182     p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
183
184     p_spu->p_sys->i_x_end        = p_sys->i_x_start + p_sys->i_width - 1;
185     p_spu->p_sys->i_y_end        = p_sys->i_y_start + p_sys->i_height - 1;
186
187     /* FIXME: use aspect ratio for x? */
188     p_spu->i_x        = p_sys->i_x_start * 3 / 4; 
189     p_spu->i_y        = p_sys->i_y_start;
190     p_spu->i_width    = p_sys->i_width;
191     p_spu->i_height   = p_sys->i_height;
192
193     p_spu->i_start    = p_sys->i_pts;
194     p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration * 10);
195     
196     p_spu->p_sys->b_crop  = VLC_FALSE;
197     p_spu->p_sys->i_debug = p_sys->i_debug;
198
199     /* Get display time now. If we do it later, we may miss the PTS. */
200     p_spu->p_sys->i_pts = p_sys->i_pts;
201
202     /* Attach to our input thread */
203     p_spu->p_sys->p_input = vlc_object_find( p_dec,
204                                              VLC_OBJECT_INPUT, FIND_PARENT );
205
206     /* We try to display it */
207     if( ParseImage( p_dec, p_spu ) )
208     {
209         /* There was a parse error, delete the subpicture */
210         vout_DestroySubPicture( p_sys->p_vout, p_spu );
211         return;
212     }
213
214     /* SPU is finished - we can ask the video output to display it */
215     vout_DisplaySubPicture( p_sys->p_vout, p_spu );
216
217 }
218
219 /* Advance pointer to image pointer, update internal i_remaining counter
220    and check that we haven't goine too far  in the image data. */
221 #define advance_color_pointer_byte                                      \
222   p++;                                                                  \
223   i_remaining=4;                                                        \
224   if (p >= maxp) {                                                      \
225     msg_Warn( p_dec,                                                    \
226               "broken subtitle - tried to access beyond end "           \
227               "in image extraction");                                   \
228     return VLC_EGENERIC;                                                \
229   }                                                                     \
230
231 #define advance_color_pointer                                           \
232   i_remaining--;                                                        \
233   if ( i_remaining == 0 ) {                                             \
234     advance_color_pointer_byte;                                         \
235   }                                                                     
236
237 /* Get the next field - either a palette index or a RLE count for
238    color 0.  To do this we use byte image pointer p, and i_remaining
239    which indicates where we are in the byte.
240 */
241 static inline ogt_color_t 
242 ExtractField(uint8_t *p, unsigned int i_remaining) 
243 {
244   return ( ( *p >> 2*(i_remaining-1) ) & 0x3 );
245 }
246
247 /* Scales down (reduces size) of p_dest in the x direction as 
248    determined through aspect ratio x_scale by y_scale. Scaling
249    is done in place. p_spu->i_width, is updated to new width
250
251    The aspect ratio is assumed to be between 1/2 and 1.
252 */
253 static void
254 ScaleX( decoder_t *p_dec, subpicture_t *p_spu, 
255         unsigned int i_scale_x, unsigned int i_scale_y )
256 {
257   int i_row, i_col;
258
259   decoder_sys_t *p_sys = p_dec->p_sys;
260   uint8_t *p_src1 = p_spu->p_sys->p_data;
261   uint8_t *p_src2 = p_src1 + PIXEL_SIZE;
262   uint8_t *p_dst  = p_src1;
263   unsigned int i_new_width = (p_spu->i_width * i_scale_x) / i_scale_y ;
264   unsigned int used=0;  /* Number of bytes used up in p_src1. */
265
266   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_TRANSFORM) , 
267              "Old width: %d, new width: %d", 
268              p_spu->i_width, i_new_width);
269   
270   for ( i_row=0; i_row <= p_spu->i_height - 1; i_row++ ) {
271
272     if (used != 0) {
273       /* Discard the remaining piece of the column of the previous line*/
274       used=0;
275       p_src1 = p_src2;
276       p_src2 += PIXEL_SIZE;
277     }
278     
279     for ( i_col=0; i_col <= p_spu->i_width - 2; i_col++ ) {
280       unsigned int i;
281       unsigned int w1= i_scale_x - used;
282       unsigned int w2= i_scale_y - w1;
283
284       used = w2;
285       for (i = 0; i < PIXEL_SIZE; i++ ) {
286         *p_dst = ( (*p_src1 * w1) + (*p_src2 * w2) ) / i_scale_y;
287         p_src1++; p_src2++; p_dst++;
288       }
289
290       if (i_scale_x == used) {
291         /* End of last pixel was end of p_src2. */
292         p_src1 = p_src2;
293         p_src2 += PIXEL_SIZE;
294         i_col++;
295         used = 0;
296       }
297     }
298   }
299   p_spu->i_width = i_new_width;
300
301   if ( p_sys && p_sys->i_debug & DECODE_DBG_TRANSFORM )
302   { 
303     ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
304     for ( i_row=0; i_row < p_spu->i_height - 1; i_row++ ) {
305       for ( i_col=0; i_col < p_spu->i_width - 1; i_col++ ) {
306         printf("%1x", p_source->s.t);
307         p_source++;
308       }
309       printf("\n");
310     }
311   }
312
313 }
314
315 /*****************************************************************************
316  * ParseImage: parse the image part of the subtitle
317  *****************************************************************************
318  This part parses the subtitle graphical data and stores it in a more
319  convenient structure for later rendering. 
320
321  The image is encoded using two bits per pixel that select a palette
322  entry except that value 0 starts a limited run-length encoding for
323  color 0.  When 0 is seen, the next two bits encode one less than the
324  number of pixels, so we can encode run lengths from 1 to 4. These get
325  filled with the color in palette entry 0.
326
327  The encoding of each line is padded to a whole number of bytes.  The
328  first field is padded to an even byte length and the complete subtitle
329  is padded to a 4-byte multiple that always include one zero byte at
330  the end.
331
332  However we'll transform this so that that the RLE is expanded and
333  interlacing will also be removed. On output each pixel entry will by 
334  an 8-bit alpha, y, u, and v entry.
335
336  *****************************************************************************/
337 static int 
338 ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
339 {
340     decoder_sys_t *p_sys = p_dec->p_sys;
341
342     unsigned int i_field;  /* The subtitles are interlaced, are we on an
343                               even or odd scanline?  */
344
345     unsigned int i_row;    /* scanline row number */
346     unsigned int i_column; /* scanline column number */
347
348     unsigned int i_width  = p_sys->i_width;
349     unsigned int i_height = p_sys->i_height;
350
351     uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
352
353     uint8_t i_remaining;           /* number of 2-bit pixels remaining 
354                                       in byte of *p */
355     uint8_t i_pending_zero = 0;    /* number of pixels to fill with 
356                                       color zero 0..4 */
357     ogt_color_t i_color;           /* current pixel color: 0..3 */
358     uint8_t *p = p_sys->subtitle_data  + p_sys->comp_image_offset;
359     uint8_t *maxp = p + p_sys->comp_image_length;
360
361     dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d ",
362                i_width, i_height);
363
364     if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)     
365       printf("\n");
366
367     for ( i_field=0; i_field < 2; i_field++ ) {
368       i_remaining = 4;
369       for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
370         for ( i_column=0; i_column<i_width; i_column++ ) {
371
372           if ( i_pending_zero ) {
373             i_pending_zero--;
374             i_color = 0;
375           } else {
376             i_color = ExtractField( p, i_remaining);
377             advance_color_pointer;
378             if ( i_color == 0 ) {
379               i_pending_zero = ExtractField( p, i_remaining );
380               advance_color_pointer;
381               /* Fall through with i_color == 0 to output the first cell */
382             }
383           }
384
385           /* Color is 0-3. */
386           p_dest[i_row*i_width+i_column] = i_color;
387
388           if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)       
389             printf("%1d", i_color);
390
391         }
392
393         if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) 
394           printf("\n");
395
396         if ( i_remaining != 4 ) {
397           /* Lines are padded to complete bytes, ignore padding */
398           advance_color_pointer_byte;
399         }
400       }
401       p = p_sys->subtitle_data + p_sys->comp_image_offset 
402         + p_sys->second_field_offset;
403     }
404
405     /* Dump out image not interlaced... */
406     if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) {
407       uint8_t *p = p_dest;
408       printf("-------------------------------------\n++");
409       for ( i_row=0; i_row < i_height; i_row ++ ) {
410         for ( i_column=0; i_column<i_width; i_column++ ) {
411           printf("%1d", *p++ & 0x03);
412         }
413         printf("\n++");
414       }
415       printf("\n-------------------------------------\n");
416     }
417
418     /* Remove color palette by expanding pixel entries to contain the
419        palette values. We work from the free space at the end to the
420        beginning so we can expand inline.
421     */
422     {
423       int n = (i_height * i_width) - 1;
424       uint8_t    *p_from = p_dest;
425       ogt_yuvt_t *p_to   = (ogt_yuvt_t *) p_dest;
426       
427       for ( ; n >= 0 ; n-- ) {
428         p_to[n] = p_sys->pi_palette[p_from[n]];
429       }
430     }
431
432     /* The video is automatically scaled. However subtitle bitmaps
433        assume a 1:1 aspect ratio. So we need to scale to compensate for
434        or undo the effects of video output scaling. 
435     */
436     /* FIXME do the right scaling depending on vout. It may not be 4:3 */
437     ScaleX( p_dec, p_spu, 3, 4 );
438
439     return VLC_SUCCESS;
440 }
441
442 /*****************************************************************************
443  * DestroySPU: subpicture destructor
444  *****************************************************************************/
445 static void DestroySPU( subpicture_t *p_spu )
446 {
447     if( p_spu->p_sys->p_input )
448     {
449         /* Detach from our input thread */
450         var_DelCallback( p_spu->p_sys->p_input, "highlight",
451                          CropCallback, p_spu );
452         vlc_object_release( p_spu->p_sys->p_input );
453     }
454
455     vlc_mutex_destroy( &p_spu->p_sys->lock );
456     free( p_spu->p_sys );
457 }
458
459 /*****************************************************************************
460  * UpdateSPU: update subpicture settings
461  *****************************************************************************
462  * This function is called from CropCallback and at initialization time, to
463  * retrieve crop information from the input.
464  *****************************************************************************/
465 static void UpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object )
466 {
467     vlc_value_t val;
468
469     if( var_Get( p_object, "highlight", &val ) )
470     {
471         return;
472     }
473
474     p_spu->p_sys->b_crop = val.b_bool;
475     if( !p_spu->p_sys->b_crop )
476     {
477         return;
478     }
479
480     var_Get( p_object, "x-start", &val );
481     p_spu->p_sys->i_x_start = val.i_int;
482     var_Get( p_object, "y-start", &val );
483     p_spu->p_sys->i_y_start = val.i_int;
484     var_Get( p_object, "x-end", &val );
485     p_spu->p_sys->i_x_end = val.i_int;
486     var_Get( p_object, "y-end", &val );
487     p_spu->p_sys->i_y_end = val.i_int;
488
489 }
490
491 /*****************************************************************************
492  * CropCallback: called when the highlight properties are changed
493  *****************************************************************************
494  * This callback is called from the input thread when we need cropping
495  *****************************************************************************/
496 static int CropCallback( vlc_object_t *p_object, char const *psz_var,
497                          vlc_value_t oldval, vlc_value_t newval, void *p_data )
498 {
499     UpdateSPU( (subpicture_t *)p_data, p_object );
500
501     return VLC_SUCCESS;
502 }
503