]> git.sesse.net Git - vlc/blob - modules/codec/ogt/cvd_parse.c
First cut at CVD subtitle unit assembly and initial parsing.
[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.2 2003/12/28 11:26:52 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 /* Advance pointer to image pointer, update internal i_remaining counter
185    and check that we haven't goine too far  in the image data. */
186 #define advance_color_pointer_byte                                      \
187   p++;                                                                  \
188   i_remaining=4;                                                        \
189   if (p >= maxp) {                                                      \
190     msg_Warn( p_dec,                                                    \
191               "broken subtitle - tried to access beyond end "           \
192               "in image extraction");                                   \
193     return VLC_EGENERIC;                                                \
194   }                                                                     \
195
196 #define advance_color_pointer                                           \
197   i_remaining--;                                                        \
198   if ( i_remaining == 0 ) {                                             \
199     advance_color_pointer_byte;                                         \
200   }                                                                     
201
202 /* Get the next field - either a palette index or a RLE count for
203    color 0.  To do this we use byte image pointer p, and i_remaining
204    which indicates where we are in the byte.
205 */
206 static inline ogt_color_t 
207 ExtractField(uint8_t *p, unsigned int i_remaining) 
208 {
209   return ( ( *p >> 2*(i_remaining-1) ) & 0x3 );
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  The image is encoded using two bits per pixel that select a palette
219  entry except that value 0 starts a limited run-length encoding for
220  color 0.  When 0 is seen, the next two bits encode one less than the
221  number of pixels, so we can encode run lengths from 1 to 4. These get
222  filled with the color in palette entry 0.
223
224  The encoding of each line is padded to a whole number of bytes.  The
225  first field is padded to an even byte length and the complete subtitle
226  is padded to a 4-byte multiple that always include one zero byte at
227  the end.
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  an 8-bit alpha, 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     dbg_print( (DECODE_DBG_CALL) , "");
240     /* To be finished...*/
241     return VLC_EGENERIC;
242
243 }
244