]> git.sesse.net Git - vlc/blob - modules/codec/ogt/cvd_parse.c
5af4107265068e65c55d12783bb3c6441988f99a
[vlc] / 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.6 2004/01/04 04:56:21 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 void E_(ParseMetaInfo)( decoder_t *p_dec  )
112 {
113   /* last packet in subtitle block. */
114   
115   decoder_sys_t *p_sys = p_dec->p_sys;
116   uint8_t       *p     = p_sys->subtitle_data + p_sys->metadata_offset;
117   uint8_t       *p_end = p + p_sys->metadata_length;
118   
119   dbg_print( (DECODE_DBG_PACKET),
120              "subtitle packet complete, size=%d", p_sys->i_spu );
121   
122   p_sys->state = SUBTITLE_BLOCK_COMPLETE;
123   p_sys->i_image++;
124   
125   for ( ; p < p_end; p += 4 ) {
126     
127     switch ( p[0] ) {
128       
129     case 0x04:  /* Display duration in 1/90000ths of a second */
130       
131       p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
132       
133       dbg_print( DECODE_DBG_PACKET, 
134                  "subtitle display duration %u", p_sys->i_duration);
135       break;
136       
137     case 0x0c:  /* Unknown */
138       dbg_print( DECODE_DBG_PACKET, 
139                  "subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x\n",
140                  p[0], p[1], p[2], p[3]);
141       break;
142       
143     case 0x17:  /* Position */
144       p_sys->i_x_start = ((p[1]&0x0f)<<6) + (p[2]>>2);
145       p_sys->i_y_start = ((p[2]&0x03)<<8) + p[3];
146       dbg_print( DECODE_DBG_PACKET, 
147                  "start position (%d,%d): %.2x %.2x %.2x", 
148                  p_sys->i_x_start, p_sys->i_y_start,
149                  p[1], p[2], p[3] );
150       break;
151       
152     case 0x1f:  /* Coordinates of the image bottom right */
153       {
154         int lastx = ((p[1]&0x0f)<<6) + (p[2]>>2);
155         int lasty = ((p[2]&0x03)<<8) + p[3];
156         p_sys->i_width  = lastx - p_sys->i_x_start + 1;
157         p_sys->i_height = lasty - p_sys->i_y_start + 1;
158         dbg_print( DECODE_DBG_PACKET, 
159                    "end position: (%d,%d): %.2x %.2x %.2x, w x h: %dx%d",
160                    lastx, lasty, p[1], p[2], p[3], 
161                    p_sys->i_width, p_sys->i_height );
162         break;
163       }
164       
165       
166     case 0x24:
167     case 0x25:
168     case 0x26:
169     case 0x27: 
170       {
171         uint8_t v = p[0]-0x24;
172         
173         /* Primary Palette */
174         dbg_print( DECODE_DBG_PACKET,
175                    "primary palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
176                    v, p[1], p[2], p[3]);
177         
178         p_sys->p_palette[v].s.y = p[1];
179         p_sys->p_palette[v].s.u = p[2];
180         p_sys->p_palette[v].s.v = p[3];
181         break;
182       }
183       
184       
185     case 0x2c:
186     case 0x2d:
187     case 0x2e:
188     case 0x2f:
189       {
190         uint8_t v = p[0]-0x2c;
191         
192         dbg_print( DECODE_DBG_PACKET,
193                    "highlight palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
194                    v, p[1], p[2], p[3]);
195         
196         /* Highlight Palette */
197         p_sys->p_palette_highlight[v].s.y = p[1];
198         p_sys->p_palette_highlight[v].s.u = p[2];
199         p_sys->p_palette_highlight[v].s.v = p[3];
200         break;
201       }
202       
203     case 0x37:
204       /* transparency for primary palette */
205       p_sys->p_palette[0].s.t = p[3] & 0x0f;
206       p_sys->p_palette[1].s.t = p[3] >> 4;
207       p_sys->p_palette[2].s.t = p[2] & 0x0f;
208       p_sys->p_palette[3].s.t = p[2] >> 4;
209       
210       dbg_print( DECODE_DBG_PACKET,
211                  "transparancy for primary palette 0..3: "
212                  "0x%0x 0x%0x 0x%0x 0x%0x",
213                  p_sys->p_palette[0].s.t,
214                  p_sys->p_palette[1].s.t,
215                  p_sys->p_palette[2].s.t,
216                  p_sys->p_palette[3].s.t );
217       
218       break;
219       
220     case 0x3f:
221       /* transparency for highlight palette */
222       p_sys->p_palette_highlight[0].s.t = p[2] & 0x0f;
223       p_sys->p_palette_highlight[1].s.t = p[2] >> 4;
224       p_sys->p_palette_highlight[2].s.t = p[1] & 0x0f;
225       p_sys->p_palette_highlight[3].s.t = p[1] >> 4;
226       
227       dbg_print( DECODE_DBG_PACKET,
228                  "transparancy for primary palette 0..3: "
229                  "0x%0x 0x%0x 0x%0x 0x%0x",
230                  p_sys->p_palette_highlight[0].s.t,
231                  p_sys->p_palette_highlight[1].s.t,
232                  p_sys->p_palette_highlight[2].s.t,
233                  p_sys->p_palette_highlight[3].s.t );
234       
235       break;
236       
237     case 0x47:
238       /* offset to first field data, we correct to make it relative
239          to comp_image_offset (usually 4) */
240       p_sys->first_field_offset =
241         (p[2] << 8) + p[3] - p_sys->comp_image_offset;
242       dbg_print( DECODE_DBG_PACKET, 
243                  "first_field_offset %d", p_sys->first_field_offset);
244       break;
245       
246     case 0x4f:
247       /* offset to second field data, we correct to make it relative to
248          comp_image_offset (usually 4) */
249       p_sys->second_field_offset =
250         (p[2] << 8) + p[3] - p_sys->comp_image_offset;
251       dbg_print( DECODE_DBG_PACKET, 
252                  "second_field_offset %d", p_sys->second_field_offset);
253       break;
254       
255     default:
256       msg_Warn( p_dec, 
257                 "unknown sequence in control header " 
258                 "0x%0x 0x%0x 0x%0x 0x%0x",
259                 p[0], p[1], p[2], p[3]);
260       
261       p_sys->subtitle_data_pos = 0;
262     }
263   }
264 }
265
266 /*****************************************************************************
267  * ParsePacket: parse an SPU packet and send it to the video output
268  *****************************************************************************
269  * This function parses the SPU packet and, if valid, sends it to the
270  * video output.
271  *****************************************************************************/
272 void 
273 E_(ParsePacket)( decoder_t *p_dec)
274 {
275     decoder_sys_t *p_sys = p_dec->p_sys;
276
277     subpicture_t  *p_spu;
278
279     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
280
281     /* Allocate the subpicture internal data. */
282     p_spu = vout_CreateSubPicture( p_sys->p_vout, MEMORY_SUBPICTURE );
283     if( p_spu == NULL )
284     {
285         return;
286     }
287
288     /* In ParseImage we expand the run-length encoded color 0's; also
289        we expand pixels and remove the color palette. This should
290        facilitate scaling and antialiasing and speed up rendering.
291     */
292     p_spu->p_sys = malloc( sizeof( subpicture_sys_t ) 
293                            + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
294
295     /* Fill the p_spu structure */
296     vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
297
298     p_spu->pf_render  = VCDSubRender;
299     p_spu->pf_destroy = VCDSubDestroySPU;
300     p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
301
302     p_spu->p_sys->i_x_end        = p_sys->i_x_start + p_sys->i_width - 1;
303     p_spu->p_sys->i_y_end        = p_sys->i_y_start + p_sys->i_height - 1;
304
305     /* FIXME: use aspect ratio for x? */
306     p_spu->i_x        = p_sys->i_x_start * 3 / 4; 
307     p_spu->i_y        = p_sys->i_y_start;
308     p_spu->i_width    = p_sys->i_width;
309     p_spu->i_height   = p_sys->i_height;
310
311     p_spu->i_start    = p_sys->i_pts;
312     p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration * 5);
313     
314     p_spu->p_sys->b_crop  = VLC_FALSE;
315     p_spu->p_sys->i_debug = p_sys->i_debug;
316
317     /* Get display time now. If we do it later, we may miss the PTS. */
318     p_spu->p_sys->i_pts = p_sys->i_pts;
319
320     /* Attach to our input thread */
321     p_spu->p_sys->p_input = vlc_object_find( p_dec,
322                                              VLC_OBJECT_INPUT, FIND_PARENT );
323
324     /* We try to display it */
325     if( ParseImage( p_dec, p_spu ) )
326     {
327         /* There was a parse error, delete the subpicture */
328         vout_DestroySubPicture( p_sys->p_vout, p_spu );
329         return;
330     }
331
332     /* SPU is finished - we can ask the video output to display it */
333     vout_DisplaySubPicture( p_sys->p_vout, p_spu );
334
335 }
336
337 #define advance_color_byte_pointer                                      \
338   p++;                                                                  \
339   i_nibble_field = 2;                                                   \
340   /*                                                                    \
341    * This is wrong, it may exceed maxp if it is the last, check         \
342    * should be moved to use location or the algorithm changed to        \
343    * that in vob2sub                                                    \
344   */                                                                    \
345   if (p >= maxp) {                                                      \
346     msg_Warn( p_dec,                                                    \
347               "broken subtitle - overflow while decoding "              \
348               " padding (%d,%d,%d)\n",                                  \
349               i_field, i_row, i_column );                               \
350     return VLC_EGENERIC;                                                \
351   }                                                                     
352
353 #define CVD_FIELD_BITS (4)
354 #define CVD_FIELD_MASK  ((1<<CVD_FIELD_BITS) - 1) 
355
356 /* Get the next field - a 2-bit palette index and a run count.  To do
357    this we use byte image pointer p, and i_nibble_field which
358    indicates where we are in the byte.
359 */
360 static inline uint8_t
361 ExtractField(uint8_t *p, uint8_t i_nibble_field) 
362 {
363   return ( ( *p >> (CVD_FIELD_BITS*(i_nibble_field-1)) ) & CVD_FIELD_MASK );
364 }
365
366 /*****************************************************************************
367  * ParseImage: parse the image part of the subtitle
368  *****************************************************************************
369  This part parses the subtitle graphical data and stores it in a more
370  convenient structure for later rendering. 
371
372  Image data comes interlaced and is run-length encoded (RLE). Each
373  field is a four-bit nibbles that is further subdivided in a two-bit
374  repeat count and a two-bit color number - up to three pixels can be
375  described in four bits.  What a 0 repeat count means is unknown.  It
376  might be used for RLE extension.  There is a special case of a 0
377  repeat count though.  When the full nibble is zero, the rest of the
378  line is filled with the color value in the next nibble.  It is
379  unknown what happens if the color value is greater than three.  The
380  rest seems to use a 4-entries palette.  It is not impossible that the
381  fill-line complete case above is not as described and the zero repeat
382  count means fill line.  The sample code never produces this, so it
383  may be untested.
384
385  However we'll transform this so that that the RLE is expanded and
386  interlacing will also be removed. On output each pixel entry will by 
387  a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
388
389  *****************************************************************************/
390 static int 
391 ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
392 {
393     decoder_sys_t *p_sys = p_dec->p_sys;
394
395     uint8_t i_field;       /* The subtitles are interlaced, are we on an
396                               even or odd scanline?  */
397     unsigned int i_row;    /* scanline row number */
398     unsigned int i_column; /* scanline column number */
399
400     unsigned int i_width  = p_sys->i_width;
401     unsigned int i_height = p_sys->i_height;
402
403     uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
404
405     uint8_t i_nibble_field;    /* The 2-bit pixels remaining in byte of *p.
406                                   Has value 0..2. */
407     vlc_bool_t b_filling;      /* Filling i_color to the of the line. */
408     uint8_t i_pending = 0;     /* number of pixels to fill with 
409                                   color zero 0..3 */
410     ogt_color_t i_color=0;     /* current pixel color: 0..3 */
411     uint8_t *p = p_sys->subtitle_data  + p_sys->comp_image_offset;
412     uint8_t *maxp = p + p_sys->comp_image_length;
413
414     dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d",
415                i_width, i_height);
416
417     if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)     
418       printf("\n");
419
420     i_pending = 0;
421
422     for ( i_field=0; i_field < 2; i_field++ ) {
423       i_nibble_field = 2;  /* 4-bit pieces available in *p */
424
425 #if 0
426       unsigned int i;
427       int8_t *b=p;
428       for (i=0; i< i_width * i_height; i++)
429         printf ("%02x", b[i]);
430       printf("\n");
431 #endif
432     
433       for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
434         b_filling   = VLC_FALSE;
435         for ( i_column=0; i_column<i_width; i_column++ ) {
436           if ( i_pending ) {
437             /* We are in the middle of a RLE expansion, just decrement and 
438                fall through with current color value */
439             i_pending--;
440           } else if ( b_filling ) {
441             /* We are just filling to the end of line with one color, just
442                reuse current color value */
443           } else {
444             uint8_t i_val = ExtractField(p, i_nibble_field--);
445             if ( i_nibble_field == 0 ) {
446               advance_color_byte_pointer;
447             }
448             if ( i_val == 0 ) {
449               /* fill the rest of the line with next color */
450               i_color = ExtractField( p, i_nibble_field-- );
451               if ( i_nibble_field == 0 ) {
452                 p++;
453                 i_nibble_field=2;
454                 /*
455                   This is wrong, it may exceed maxp if it is the
456                   last, check should be moved to use location or the
457                   algorithm changed to that in vob2sub
458                 */
459                 if (p >= maxp) {
460                   msg_Warn( p_dec, 
461                             "broken subtitle - overflow while decoding "
462                             " filling (%d,%d,%d)", 
463                               i_field, i_row, i_column);
464                   /* return VLC_EGENERIC; */
465                 }
466               }
467               b_filling = VLC_TRUE;
468             } else {
469               /* Normal case: get color and repeat count, 
470                  this iteration will  output the first (or only) 
471                  instance */
472               i_pending = (i_val >> 2);
473               i_color = i_val & 0x3;
474               /* This time counts against the total */
475               i_pending--;
476             }
477           }
478           /* Color is 0-3. */
479           p_dest[i_row*i_width+i_column] = i_color;
480           
481           if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)       
482             printf("%1d", i_color);
483           
484         }
485         
486         if ( i_nibble_field == 1 ) {
487           advance_color_byte_pointer;
488         }
489
490         if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) 
491           printf("\n");
492       }
493     }
494
495     if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE)) {
496       /* Dump out image not interlaced... */
497       VCDSubDumpImage( p_dest, i_height, i_width );
498     }
499
500 #ifdef HAVE_LIBPNG
501     if (p_sys && (p_sys->i_debug & DECODE_DBG_PNG)) {
502 #define TEXT_COUNT 2
503       /* Dump image to a file in PNG format. */
504       char filename[300];
505       png_text text_ptr[TEXT_COUNT];
506
507       text_ptr[0].key = "Preparer";
508       text_ptr[0].text = "VLC";
509       text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
510       text_ptr[1].key = "Description";
511       text_ptr[1].text = "CVD Subtitle";
512       text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
513
514       snprintf(filename, 300, "%s%d.png", "/tmp/vlc-cvd-sub", p_sys->i_image);
515       VCDSubDumpPNG( p_dest, p_dec, i_height, i_width, filename,
516                      text_ptr, TEXT_COUNT );
517     }
518 #endif /*HAVE_LIBPNG*/
519
520
521     VCDInlinePalette( p_dest, p_sys, i_height, i_width );
522
523     /* The video is automatically scaled. However subtitle bitmaps
524        assume a 1:1 aspect ratio. So we need to scale to compensate for
525        or undo the effects of video output scaling. 
526     */
527     /* FIXME do the right scaling depending on vout. It may not be 4:3 */
528     VCDSubScaleX( p_dec, p_spu, 3, 4 );
529
530     /* To be finished...*/
531     return VLC_SUCCESS;
532
533 }
534