1 /*****************************************************************************
2 * parse.c: Philips OGT (SVCD subtitle) packet parser
3 *****************************************************************************
4 * Copyright (C) 2003 VideoLAN
5 * $Id: cvd_parse.c,v 1.4 2003/12/30 04:43:52 rocky Exp $
7 * Authors: Rocky Bernstein
9 * Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
10 * Sam Hocevar <sam@zoy.org>
11 * Laurent Aimar <fenrir@via.ecp.fr>
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.
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.
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 *****************************************************************************/
28 /*****************************************************************************
30 *****************************************************************************/
33 #include <vlc/decoder.h>
40 /* An image color is a two-bit palette entry: 0..3 */
41 typedef uint8_t ogt_color_t;
43 /*****************************************************************************
45 *****************************************************************************/
46 static int ParseImage ( decoder_t *, subpicture_t * );
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.
54 CVD subtitles are different in severl ways from SVCD OGT subtitles.
55 First, the image comes first and the metadata is at the end. So
56 that the metadata can be found easily, the subtitle packet starts
57 with two bytes (everything is big-endian again) that give the total
58 size of the subtitle data and the offset to the metadata - i.e. size
59 of the image data plus the four bytes at the beginning.
61 Image data comes interlaced is run-length encoded. Each field is a
62 four-bit nibble. Each nibble contains a two-bit repeat count and a
63 two-bit color number so that up to three pixels can be described in
64 four bits. The function of a 0 repeat count is unknown; it might be
65 used for RLE extension. However when the full nibble is zero, the
66 rest of the line is filled with the color value in the next nibble.
67 It is unknown what happens if the color value is greater than three.
68 The rest seems to use a 4-entries palette. It is not impossible
69 that the fill-line complete case above is not as described and the
70 zero repeat count means fill line. The sample code never produces
71 this, so it may be untested.
73 The metadata section does not follow a fixed pattern, every
74 metadata item consists of a tag byte followed by parameters. In all
75 cases known, the block (including the tag byte) is exactly four
76 bytes in length. Read the code for the rest.
79 void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
81 decoder_sys_t *p_sys = p_dec->p_sys;
82 u_int8_t *p = p_buffer+1;
84 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET),
85 "header: 0x%02x 0x%02x 0x%02x 0x%02x, 0x%02x, 0x%02x, size: %i",
86 p_buffer[0], p_buffer[1], p_buffer[2], p_buffer[3],
87 p_buffer[4], p_buffer[5],
90 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
92 p_sys->i_pts = p_block->i_pts;
93 p_sys->i_spu_size = (p[0] << 8) + p[1] + 4; p += 2;
95 /* FIXME: check data sanity */
96 p_sys->metadata_offset = GETINT16(p);
97 p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_offset;
99 p_sys->comp_image_offset = 4;
100 p_sys->comp_image_length = p_sys->metadata_offset - p_sys->comp_image_offset;
102 dbg_print(DECODE_DBG_PACKET, "total size: %d image size: %d\n",
103 p_sys->i_spu_size, p_sys->comp_image_length);
108 /*****************************************************************************
109 * ParsePacket: parse an SPU packet and send it to the video output
110 *****************************************************************************
111 * This function parses the SPU packet and, if valid, sends it to the
113 *****************************************************************************/
115 E_(ParsePacket)( decoder_t *p_dec)
117 decoder_sys_t *p_sys = p_dec->p_sys;
121 dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
123 /* Allocate the subpicture internal data. */
124 p_spu = vout_CreateSubPicture( p_sys->p_vout, MEMORY_SUBPICTURE );
130 /* In ParseImage we expand the run-length encoded color 0's; also
131 we expand pixels and remove the color palette. This should
132 facilitate scaling and antialiasing and speed up rendering.
134 p_spu->p_sys = malloc( sizeof( subpicture_sys_t )
135 + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
137 /* Fill the p_spu structure */
138 vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
140 p_spu->pf_render = VCDSubRender;
141 p_spu->pf_destroy = VCDSubDestroySPU;
142 p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
144 p_spu->p_sys->i_x_end = p_sys->i_x_start + p_sys->i_width - 1;
145 p_spu->p_sys->i_y_end = p_sys->i_y_start + p_sys->i_height - 1;
147 /* FIXME: use aspect ratio for x? */
148 p_spu->i_x = p_sys->i_x_start * 3 / 4;
149 p_spu->i_y = p_sys->i_y_start;
150 p_spu->i_width = p_sys->i_width;
151 p_spu->i_height = p_sys->i_height;
153 p_spu->i_start = p_sys->i_pts;
154 p_spu->i_stop = p_sys->i_pts + (p_sys->i_duration * 5);
156 p_spu->p_sys->b_crop = VLC_FALSE;
157 p_spu->p_sys->i_debug = p_sys->i_debug;
159 /* Get display time now. If we do it later, we may miss the PTS. */
160 p_spu->p_sys->i_pts = p_sys->i_pts;
162 /* Attach to our input thread */
163 p_spu->p_sys->p_input = vlc_object_find( p_dec,
164 VLC_OBJECT_INPUT, FIND_PARENT );
166 /* We try to display it */
167 if( ParseImage( p_dec, p_spu ) )
169 /* There was a parse error, delete the subpicture */
170 vout_DestroySubPicture( p_sys->p_vout, p_spu );
174 /* SPU is finished - we can ask the video output to display it */
175 vout_DisplaySubPicture( p_sys->p_vout, p_spu );
179 #define advance_color_byte_pointer \
181 i_nibble_field = 2; \
183 * This is wrong, it may exceed maxp if it is the last, check \
184 * should be moved to use location or the algorithm changed to \
189 "broken subtitle - overflow while decoding " \
190 " padding (%d,%d,%d)\n", \
191 i_field, i_row, i_column ); \
192 return VLC_EGENERIC; \
195 #define CVD_FIELD_BITS (4)
196 #define CVD_FIELD_MASK ((1<<CVD_FIELD_BITS) - 1)
198 /* Get the next field - a 2-bit palette index and a run count. To do
199 this we use byte image pointer p, and i_nibble_field which
200 indicates where we are in the byte.
202 static inline uint8_t
203 ExtractField(uint8_t *p, uint8_t i_nibble_field)
205 return ( ( *p >> (CVD_FIELD_BITS*(i_nibble_field-1)) ) & CVD_FIELD_MASK );
208 /*****************************************************************************
209 * ParseImage: parse the image part of the subtitle
210 *****************************************************************************
211 This part parses the subtitle graphical data and stores it in a more
212 convenient structure for later rendering.
214 Image data comes interlaced and is run-length encoded (RLE). Each
215 field is a four-bit nibbles that is further subdivided in a two-bit
216 repeat count and a two-bit color number - up to three pixels can be
217 described in four bits. What a 0 repeat count means is unknown. It
218 might be used for RLE extension. There is a special case of a 0
219 repeat count though. When the full nibble is zero, the rest of the
220 line is filled with the color value in the next nibble. It is
221 unknown what happens if the color value is greater than three. The
222 rest seems to use a 4-entries palette. It is not impossible that the
223 fill-line complete case above is not as described and the zero repeat
224 count means fill line. The sample code never produces this, so it
227 However we'll transform this so that that the RLE is expanded and
228 interlacing will also be removed. On output each pixel entry will by
229 a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
231 *****************************************************************************/
233 ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
235 decoder_sys_t *p_sys = p_dec->p_sys;
237 uint8_t i_field; /* The subtitles are interlaced, are we on an
238 even or odd scanline? */
239 unsigned int i_row; /* scanline row number */
240 unsigned int i_column; /* scanline column number */
242 unsigned int i_width = p_sys->i_width;
243 unsigned int i_height = p_sys->i_height;
245 uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
247 uint8_t i_nibble_field; /* The 2-bit pixels remaining in byte of *p.
249 vlc_bool_t b_filling; /* Filling i_color to the of the line. */
250 uint8_t i_pending = 0; /* number of pixels to fill with
252 ogt_color_t i_color=0; /* current pixel color: 0..3 */
253 uint8_t *p = p_sys->subtitle_data + p_sys->comp_image_offset;
254 uint8_t *maxp = p + p_sys->comp_image_length;
256 dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d",
259 if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
264 for ( i_field=0; i_field < 2; i_field++ ) {
265 i_nibble_field = 2; /* 4-bit pieces available in *p */
267 for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
268 b_filling = VLC_FALSE;
269 for ( i_column=0; i_column<i_width; i_column++ ) {
271 /* We are in the middle of a RLE expansion, just decrement and
272 fall through with current color value */
274 } else if ( b_filling ) {
275 /* We are just filling to the end of line with one color, just
276 reuse current color value */
278 uint8_t i_val = ExtractField(p, i_nibble_field--);
279 if ( i_nibble_field == 0 ) {
280 advance_color_byte_pointer;
283 /* fill the rest of the line with next color */
284 i_color = ExtractField( p, i_nibble_field-- );
285 if ( i_nibble_field == 0 ) {
289 This is wrong, it may exceed maxp if it is the
290 last, check should be moved to use location or the
291 algorithm changed to that in vob2sub
295 "broken subtitle - overflow while decoding "
296 " filling (%d,%d,%d)",
297 i_field, i_row, i_column);
298 /* return VLC_EGENERIC; */
301 b_filling = VLC_TRUE;
303 /* Normal case: get color and repeat count,
304 this iteration will output the first (or only)
306 i_pending = (i_val >> 2);
307 i_color = i_val & 0x3;
308 /* This time counts against the total */
313 p_dest[i_row*i_width+i_column] = i_color;
315 if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
316 printf("%1d", i_color);
320 if ( i_nibble_field == 1 ) {
321 advance_color_byte_pointer;
324 if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)
329 /* Dump out image not interlaced... */
330 if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) {
332 printf("-------------------------------------\n++");
333 for ( i_row=0; i_row < i_height; i_row ++ ) {
334 for ( i_column=0; i_column<i_width; i_column++ ) {
335 printf("%1d", *p++ & 0x03);
339 printf("\n-------------------------------------\n");
342 VCDInlinePalette( p_dest, p_sys, i_height, i_width );
344 /* The video is automatically scaled. However subtitle bitmaps
345 assume a 1:1 aspect ratio. So we need to scale to compensate for
346 or undo the effects of video output scaling.
348 /* FIXME do the right scaling depending on vout. It may not be 4:3 */
349 VCDSubScaleX( p_dec, p_spu, 3, 4 );
351 /* To be finished...*/