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