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