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