ogt.c cvd.c, subtitle.h: move common debug string help into subtitle.h
[vlc.git] / modules / codec / ogt / cvd_parse.c
1 /*****************************************************************************
2  * parse.c: Philips OGT (SVCD subtitle) packet parser
3  *****************************************************************************
4  * Copyright (C) 2003, 2004 VideoLAN
5  * $Id: cvd_parse.c,v 1.5 2004/01/03 12:54:56 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 "cvd.h"
38 #include "common.h"
39
40 #ifdef HAVE_LIBPNG
41 #include <png.h>
42 #endif
43
44 /* An image color is a two-bit palette entry: 0..3 */ 
45 typedef uint8_t ogt_color_t;
46
47 /*****************************************************************************
48  * Local prototypes.
49  *****************************************************************************/
50 static int  ParseImage         ( decoder_t *, subpicture_t * );
51
52 /*
53   We do not have information on the subtitle format used on CVD's
54   except the submux sample code and a couple of samples of dubious
55   origin. Thus, this is the result of reading some code whose
56   correctness is not known and some experimentation.
57   
58   CVD subtitles are different in severl ways from SVCD OGT subtitles.
59   First, the image comes first and the metadata is at the end.  So
60   that the metadata can be found easily, the subtitle packet starts
61   with two bytes (everything is big-endian again) that give the total
62   size of the subtitle data and the offset to the metadata - i.e. size
63   of the image data plus the four bytes at the beginning.
64  
65   Image data comes interlaced is run-length encoded.  Each field is a
66   four-bit nibble. Each nibble contains a two-bit repeat count and a
67   two-bit color number so that up to three pixels can be described in
68   four bits.  The function of a 0 repeat count is unknown; it might be
69   used for RLE extension.  However when the full nibble is zero, the
70   rest of the line is filled with the color value in the next nibble.
71   It is unknown what happens if the color value is greater than three.
72   The rest seems to use a 4-entries palette.  It is not impossible
73   that the fill-line complete case above is not as described and the
74   zero repeat count means fill line.  The sample code never produces
75   this, so it may be untested.
76  
77   The metadata section does not follow a fixed pattern, every
78   metadata item consists of a tag byte followed by parameters. In all
79   cases known, the block (including the tag byte) is exactly four
80   bytes in length.  Read the code for the rest.
81 */
82
83 void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
84 {
85   decoder_sys_t *p_sys = p_dec->p_sys;
86   u_int8_t *p = p_buffer+1;
87
88   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET), 
89              "header: 0x%02x 0x%02x 0x%02x 0x%02x, 0x%02x, 0x%02x, size: %i",
90              p_buffer[0], p_buffer[1], p_buffer[2], p_buffer[3],
91              p_buffer[4], p_buffer[5],
92              p_block->i_buffer);
93   
94   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
95
96   p_sys->i_pts    = p_block->i_pts;
97   p_sys->i_spu_size = (p[0] << 8) + p[1] + 4; p += 2;
98
99   /* FIXME: check data sanity */
100   p_sys->metadata_offset = GETINT16(p);
101   p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_offset;
102
103   p_sys->comp_image_offset = 4;
104   p_sys->comp_image_length = p_sys->metadata_offset - p_sys->comp_image_offset;
105   
106   dbg_print(DECODE_DBG_PACKET, "total size: %d  image size: %d\n",
107             p_sys->i_spu_size, p_sys->comp_image_length);
108
109 }
110
111
112 /*****************************************************************************
113  * ParsePacket: parse an SPU packet and send it to the video output
114  *****************************************************************************
115  * This function parses the SPU packet and, if valid, sends it to the
116  * video output.
117  *****************************************************************************/
118 void 
119 E_(ParsePacket)( decoder_t *p_dec)
120 {
121     decoder_sys_t *p_sys = p_dec->p_sys;
122
123     subpicture_t  *p_spu;
124
125     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
126
127     /* Allocate the subpicture internal data. */
128     p_spu = vout_CreateSubPicture( p_sys->p_vout, MEMORY_SUBPICTURE );
129     if( p_spu == NULL )
130     {
131         return;
132     }
133
134     /* In ParseImage we expand the run-length encoded color 0's; also
135        we expand pixels and remove the color palette. This should
136        facilitate scaling and antialiasing and speed up rendering.
137     */
138     p_spu->p_sys = malloc( sizeof( subpicture_sys_t ) 
139                            + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
140
141     /* Fill the p_spu structure */
142     vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
143
144     p_spu->pf_render  = VCDSubRender;
145     p_spu->pf_destroy = VCDSubDestroySPU;
146     p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
147
148     p_spu->p_sys->i_x_end        = p_sys->i_x_start + p_sys->i_width - 1;
149     p_spu->p_sys->i_y_end        = p_sys->i_y_start + p_sys->i_height - 1;
150
151     /* FIXME: use aspect ratio for x? */
152     p_spu->i_x        = p_sys->i_x_start * 3 / 4; 
153     p_spu->i_y        = p_sys->i_y_start;
154     p_spu->i_width    = p_sys->i_width;
155     p_spu->i_height   = p_sys->i_height;
156
157     p_spu->i_start    = p_sys->i_pts;
158     p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration * 5);
159     
160     p_spu->p_sys->b_crop  = VLC_FALSE;
161     p_spu->p_sys->i_debug = p_sys->i_debug;
162
163     /* Get display time now. If we do it later, we may miss the PTS. */
164     p_spu->p_sys->i_pts = p_sys->i_pts;
165
166     /* Attach to our input thread */
167     p_spu->p_sys->p_input = vlc_object_find( p_dec,
168                                              VLC_OBJECT_INPUT, FIND_PARENT );
169
170     /* We try to display it */
171     if( ParseImage( p_dec, p_spu ) )
172     {
173         /* There was a parse error, delete the subpicture */
174         vout_DestroySubPicture( p_sys->p_vout, p_spu );
175         return;
176     }
177
178     /* SPU is finished - we can ask the video output to display it */
179     vout_DisplaySubPicture( p_sys->p_vout, p_spu );
180
181 }
182
183 #define advance_color_byte_pointer                                      \
184   p++;                                                                  \
185   i_nibble_field = 2;                                                   \
186   /*                                                                    \
187    * This is wrong, it may exceed maxp if it is the last, check         \
188    * should be moved to use location or the algorithm changed to        \
189    * that in vob2sub                                                    \
190   */                                                                    \
191   if (p >= maxp) {                                                      \
192     msg_Warn( p_dec,                                                    \
193               "broken subtitle - overflow while decoding "              \
194               " padding (%d,%d,%d)\n",                                  \
195               i_field, i_row, i_column );                               \
196     return VLC_EGENERIC;                                                \
197   }                                                                     
198
199 #define CVD_FIELD_BITS (4)
200 #define CVD_FIELD_MASK  ((1<<CVD_FIELD_BITS) - 1) 
201
202 /* Get the next field - a 2-bit palette index and a run count.  To do
203    this we use byte image pointer p, and i_nibble_field which
204    indicates where we are in the byte.
205 */
206 static inline uint8_t
207 ExtractField(uint8_t *p, uint8_t i_nibble_field) 
208 {
209   return ( ( *p >> (CVD_FIELD_BITS*(i_nibble_field-1)) ) & CVD_FIELD_MASK );
210 }
211
212 /*****************************************************************************
213  * ParseImage: parse the image part of the subtitle
214  *****************************************************************************
215  This part parses the subtitle graphical data and stores it in a more
216  convenient structure for later rendering. 
217
218  Image data comes interlaced and is run-length encoded (RLE). Each
219  field is a four-bit nibbles that is further subdivided in a two-bit
220  repeat count and a two-bit color number - up to three pixels can be
221  described in four bits.  What a 0 repeat count means is unknown.  It
222  might be used for RLE extension.  There is a special case of a 0
223  repeat count though.  When the full nibble is zero, the rest of the
224  line is filled with the color value in the next nibble.  It is
225  unknown what happens if the color value is greater than three.  The
226  rest seems to use a 4-entries palette.  It is not impossible that the
227  fill-line complete case above is not as described and the zero repeat
228  count means fill line.  The sample code never produces this, so it
229  may be untested.
230
231  However we'll transform this so that that the RLE is expanded and
232  interlacing will also be removed. On output each pixel entry will by 
233  a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
234
235  *****************************************************************************/
236 static int 
237 ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
238 {
239     decoder_sys_t *p_sys = p_dec->p_sys;
240
241     uint8_t i_field;       /* The subtitles are interlaced, are we on an
242                               even or odd scanline?  */
243     unsigned int i_row;    /* scanline row number */
244     unsigned int i_column; /* scanline column number */
245
246     unsigned int i_width  = p_sys->i_width;
247     unsigned int i_height = p_sys->i_height;
248
249     uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
250
251     uint8_t i_nibble_field;    /* The 2-bit pixels remaining in byte of *p.
252                                   Has value 0..2. */
253     vlc_bool_t b_filling;      /* Filling i_color to the of the line. */
254     uint8_t i_pending = 0;     /* number of pixels to fill with 
255                                   color zero 0..3 */
256     ogt_color_t i_color=0;     /* current pixel color: 0..3 */
257     uint8_t *p = p_sys->subtitle_data  + p_sys->comp_image_offset;
258     uint8_t *maxp = p + p_sys->comp_image_length;
259
260     dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d",
261                i_width, i_height);
262
263     if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)     
264       printf("\n");
265
266     i_pending = 0;
267
268     for ( i_field=0; i_field < 2; i_field++ ) {
269       i_nibble_field = 2;  /* 4-bit pieces available in *p */
270
271 #if 0
272       unsigned int i;
273       int8_t *b=p;
274       for (i=0; i< i_width * i_height; i++)
275         printf ("%02x", b[i]);
276       printf("\n");
277 #endif
278     
279       for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
280         b_filling   = VLC_FALSE;
281         for ( i_column=0; i_column<i_width; i_column++ ) {
282           if ( i_pending ) {
283             /* We are in the middle of a RLE expansion, just decrement and 
284                fall through with current color value */
285             i_pending--;
286           } else if ( b_filling ) {
287             /* We are just filling to the end of line with one color, just
288                reuse current color value */
289           } else {
290             uint8_t i_val = ExtractField(p, i_nibble_field--);
291             if ( i_nibble_field == 0 ) {
292               advance_color_byte_pointer;
293             }
294             if ( i_val == 0 ) {
295               /* fill the rest of the line with next color */
296               i_color = ExtractField( p, i_nibble_field-- );
297               if ( i_nibble_field == 0 ) {
298                 p++;
299                 i_nibble_field=2;
300                 /*
301                   This is wrong, it may exceed maxp if it is the
302                   last, check should be moved to use location or the
303                   algorithm changed to that in vob2sub
304                 */
305                 if (p >= maxp) {
306                   msg_Warn( p_dec, 
307                             "broken subtitle - overflow while decoding "
308                             " filling (%d,%d,%d)", 
309                               i_field, i_row, i_column);
310                   /* return VLC_EGENERIC; */
311                 }
312               }
313               b_filling = VLC_TRUE;
314             } else {
315               /* Normal case: get color and repeat count, 
316                  this iteration will  output the first (or only) 
317                  instance */
318               i_pending = (i_val >> 2);
319               i_color = i_val & 0x3;
320               /* This time counts against the total */
321               i_pending--;
322             }
323           }
324           /* Color is 0-3. */
325           p_dest[i_row*i_width+i_column] = i_color;
326           
327           if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)       
328             printf("%1d", i_color);
329           
330         }
331         
332         if ( i_nibble_field == 1 ) {
333           advance_color_byte_pointer;
334         }
335
336         if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) 
337           printf("\n");
338       }
339     }
340
341     if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE)) {
342       /* Dump out image not interlaced... */
343       VCDSubDumpImage( p_dest, i_height, i_width );
344     }
345
346 #ifdef HAVE_LIBPNG
347     if (p_sys && (p_sys->i_debug & DECODE_DBG_PNG)) {
348 #define TEXT_COUNT 2
349       /* Dump image to a file in PNG format. */
350       char filename[300];
351       png_text text_ptr[TEXT_COUNT];
352
353       text_ptr[0].key = "Preparer";
354       text_ptr[0].text = "VLC";
355       text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
356       text_ptr[1].key = "Description";
357       text_ptr[1].text = "CVD Subtitle";
358       text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
359
360       snprintf(filename, 300, "%s%d.png", "/tmp/vlc-cvd-sub", p_sys->i_image);
361       VCDSubDumpPNG( p_dest, p_dec, i_height, i_width, filename,
362                      text_ptr, TEXT_COUNT );
363     }
364 #endif /*HAVE_LIBPNG*/
365
366
367     VCDInlinePalette( p_dest, p_sys, i_height, i_width );
368
369     /* The video is automatically scaled. However subtitle bitmaps
370        assume a 1:1 aspect ratio. So we need to scale to compensate for
371        or undo the effects of video output scaling. 
372     */
373     /* FIXME do the right scaling depending on vout. It may not be 4:3 */
374     VCDSubScaleX( p_dec, p_spu, 3, 4 );
375
376     /* To be finished...*/
377     return VLC_SUCCESS;
378
379 }
380