Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

svcdsub.c

00001 /*****************************************************************************
00002  * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
00003  *****************************************************************************
00004  * Copyright (C) 2003, 2004 the VideoLAN team
00005  * $Id: svcdsub.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Rocky Bernstein
00008  *          Gildas Bazin <[email protected]>
00009  *          Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
00010  *          Laurent Aimar <[email protected]>
00011  *
00012  * This program is free software; you can redistribute it and/or modify
00013  * it under the terms of the GNU General Public License as published by
00014  * the Free Software Foundation; either version 2 of the License, or
00015  * (at your option) any later version.
00016  *
00017  * This program is distributed in the hope that it will be useful,
00018  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  * GNU General Public License for more details.
00021  *
00022  * You should have received a copy of the GNU General Public License
00023  * along with this program; if not, write to the Free Software
00024  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00025  *****************************************************************************/
00026 
00027 /*****************************************************************************
00028  * Preamble
00029  *****************************************************************************/
00030 #include <vlc/vlc.h>
00031 #include <vlc/decoder.h>
00032 
00033 #include "vlc_bits.h"
00034 
00035 /*****************************************************************************
00036  * Module descriptor.
00037  *****************************************************************************/
00038 static int  DecoderOpen   ( vlc_object_t * );
00039 static int  PacketizerOpen( vlc_object_t * );
00040 static void DecoderClose  ( vlc_object_t * );
00041 
00042 #define DEBUG_TEXT \
00043      "If nonzero, this gives additional debug information." \
00044 
00045 #define DEBUG_LONGTEXT \
00046     "This integer when viewed in binary is a debugging mask\n" \
00047     "calls                 1\n" \
00048     "packet assembly info  2\n"
00049 
00050 vlc_module_begin();
00051     set_description( _("Philips OGT (SVCD subtitle) decoder") );
00052     set_shortname( N_("SVCD subtitles"));
00053     set_category( CAT_INPUT );
00054     set_subcategory( SUBCAT_INPUT_SCODEC );
00055     set_capability( "decoder", 50 );
00056     set_callbacks( DecoderOpen, DecoderClose );
00057 
00058     add_integer ( MODULE_STRING "-debug", 0, NULL,
00059                   DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
00060 
00061     add_submodule();
00062     set_description( _("Philips OGT (SVCD subtitle) packetizer") );
00063     set_capability( "packetizer", 50 );
00064     set_callbacks( PacketizerOpen, DecoderClose );
00065 vlc_module_end();
00066 
00067 /*****************************************************************************
00068  * Local prototypes
00069  *****************************************************************************/
00070 static subpicture_t *Decode( decoder_t *, block_t ** );
00071 static block_t *Packetize  ( decoder_t *, block_t ** );
00072 static block_t *Reassemble ( decoder_t *, block_t * );
00073 static void ParseHeader( decoder_t *, block_t * );
00074 static subpicture_t *DecodePacket( decoder_t *, block_t * );
00075 static void SVCDSubRenderImage( decoder_t *, block_t *, subpicture_region_t * );
00076 
00077 #define DECODE_DBG_CALL        1 /* calls */
00078 #define DECODE_DBG_PACKET      2 /* packet assembly info */
00079 
00080 #define GETINT16(p) ( (p[0] <<  8) +   p[1] )  ; p +=2;
00081 
00082 #define GETINT32(p) ( (p[0] << 24) +  (p[1] << 16) +    \
00083                       (p[2] <<  8) +  (p[3]) ) ; p += 4;
00084 
00085 typedef enum  {
00086   SUBTITLE_BLOCK_EMPTY    = 0,
00087   SUBTITLE_BLOCK_PARTIAL  = 1,
00088   SUBTITLE_BLOCK_COMPLETE = 2
00089 } packet_state_t;
00090 
00091 #ifndef DECODE_DEBUG
00092 #define DECODE_DEBUG 1
00093 #endif
00094 #if DECODE_DEBUG
00095 #define dbg_print(mask, s, args...) \
00096    if (p_sys && p_sys->i_debug & mask) \
00097      msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
00098 #else
00099 #define dbg_print(mask, s, args...)
00100 #endif
00101 
00102 struct decoder_sys_t
00103 {
00104   int      i_debug;       /* debugging mask */
00105 
00106   packet_state_t i_state; /* data-gathering state for this subtitle */
00107 
00108   block_t  *p_spu;        /* Bytes of the packet. */
00109 
00110   uint16_t i_image;       /* image number in the subtitle stream */
00111   uint8_t  i_packet;      /* packet number for above image number */
00112 
00113   int     i_spu_size;     /* goal for subtitle_data_pos while gathering,
00114                              size of used subtitle_data later */
00115 
00116   uint16_t i_image_offset;      /* offset from subtitle_data to compressed
00117                                    image data */
00118   int i_image_length;           /* size of the compressed image data */
00119   int second_field_offset;      /* offset of odd raster lines */
00120   int metadata_offset;          /* offset to data describing the image */
00121   int metadata_length;          /* length of metadata */
00122 
00123   mtime_t i_duration;   /* how long to display the image, 0 stands
00124                            for "until next subtitle" */
00125 
00126   uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
00127                                     image when displayed */
00128   uint16_t i_width, i_height;    /* dimensions in pixels of image */
00129 
00130   uint8_t p_palette[4][4];       /* Palette of colors used in subtitle */
00131 };
00132 
00133 /*****************************************************************************
00134  * DecoderOpen: open/initialize the svcdsub decoder.
00135  *****************************************************************************/
00136 static int DecoderOpen( vlc_object_t *p_this )
00137 {
00138     decoder_t     *p_dec = (decoder_t*)p_this;
00139     decoder_sys_t *p_sys;
00140 
00141     if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
00142     {
00143         return VLC_EGENERIC;
00144     }
00145 
00146     p_dec->p_sys = p_sys = calloc( 1, sizeof( decoder_sys_t ) );
00147     p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
00148 
00149     p_sys->i_image       = -1;
00150 
00151     p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
00152     p_sys->p_spu   = NULL;
00153 
00154     es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
00155 
00156     p_dec->pf_decode_sub = Decode;
00157     p_dec->pf_packetize  = Packetize;
00158 
00159     dbg_print( (DECODE_DBG_CALL) , "");
00160     return VLC_SUCCESS;
00161 }
00162 
00163 /*****************************************************************************
00164  * PacketizerOpen: open/initialize the svcdsub packetizer.
00165  *****************************************************************************/
00166 static int PacketizerOpen( vlc_object_t *p_this )
00167 {
00168     if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
00169 
00170     return VLC_SUCCESS;
00171 }
00172 
00173 /*****************************************************************************
00174  * DecoderClose: closes the svcdsub decoder/packetizer.
00175  *****************************************************************************/
00176 void DecoderClose( vlc_object_t *p_this )
00177 {
00178     decoder_t     *p_dec = (decoder_t*)p_this;
00179     decoder_sys_t *p_sys = p_dec->p_sys;
00180 
00181     if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
00182     free( p_sys );
00183 }
00184 
00185 /*****************************************************************************
00186  * Decode:
00187  *****************************************************************************/
00188 static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
00189 {
00190     block_t *p_block, *p_spu;
00191     decoder_sys_t *p_sys = p_dec->p_sys;
00192 
00193     dbg_print( (DECODE_DBG_CALL) , "");
00194 
00195     if( pp_block == NULL || *pp_block == NULL ) return NULL;
00196 
00197     p_block = *pp_block;
00198     *pp_block = NULL;
00199 
00200     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
00201 
00202     /* Parse and decode */
00203     return DecodePacket( p_dec, p_spu );
00204 }
00205 
00206 /*****************************************************************************
00207  * Packetize:
00208  *****************************************************************************/
00209 static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
00210 {
00211     block_t *p_block, *p_spu;
00212 
00213     if( pp_block == NULL || *pp_block == NULL ) return NULL;
00214 
00215     p_block = *pp_block;
00216     *pp_block = NULL;
00217 
00218     if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
00219 
00220     p_spu->i_dts = p_spu->i_pts;
00221     p_spu->i_length = 0;
00222 
00223     return p_spu;
00224 }
00225 
00226 /*****************************************************************************
00227  Reassemble:
00228 
00229  The data for single screen subtitle may come in one of many
00230  non-contiguous packets of a stream. This routine is called when the
00231  next packet in the stream comes in. The job of this routine is to
00232  parse the header, if this is the beginning, and combine the packets
00233  into one complete subtitle unit.
00234 
00235  If everything is complete, we will return a block. Otherwise return
00236  NULL.
00237 
00238 
00239  The format of the beginning of the subtitle packet that is used here.
00240 
00241    size    description
00242    -------------------------------------------
00243    byte    subtitle channel (0..7) in bits 0-3
00244    byte    subtitle packet number of this subtitle image 0-N,
00245            if the subtitle packet is complete, the top bit of the byte is 1.
00246    uint16  subtitle image number
00247 
00248  *****************************************************************************/
00249 #define SPU_HEADER_LEN 5
00250 
00251 static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
00252 {
00253     decoder_sys_t *p_sys = p_dec->p_sys;
00254     uint8_t *p_buffer;
00255     uint16_t i_expected_image;
00256     uint8_t  i_packet, i_expected_packet;
00257 
00258     if( p_block->i_buffer < SPU_HEADER_LEN )
00259     {
00260         msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
00261                  p_block->i_buffer, SPU_HEADER_LEN );
00262         block_Release( p_block );
00263         return NULL;
00264     }
00265 
00266     p_buffer = p_block->p_buffer;
00267 
00268     /* Attach to our input thread and see if subtitle is selected. */
00269     {
00270         vlc_object_t * p_input;
00271         vlc_value_t val;
00272 
00273         p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
00274 
00275         if( !p_input ) return NULL;
00276 
00277         if( var_Get( p_input, "sub-track", &val ) )
00278         {
00279             vlc_object_release( p_input );
00280             return NULL;
00281         }
00282 
00283         vlc_object_release( p_input );
00284         dbg_print( (DECODE_DBG_PACKET),
00285                    "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
00286 
00287         /* The dummy ES that the menu selection uses has an 0x70 at
00288            the head which we need to strip off. */
00289         if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
00290         {
00291             dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
00292             return NULL;
00293         }
00294     }
00295 
00296     if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
00297     {
00298         i_expected_image  = p_sys->i_image + 1;
00299         i_expected_packet = 0;
00300     }
00301     else
00302     {
00303         i_expected_image  = p_sys->i_image;
00304         i_expected_packet = p_sys->i_packet + 1;
00305     }
00306 
00307     p_buffer += 2;
00308 
00309     if( *p_buffer & 0x80 )
00310     {
00311         p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
00312         i_packet       = *p_buffer++ & 0x7F;
00313     }
00314     else
00315     {
00316         p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
00317         i_packet       = *p_buffer++;
00318     }
00319 
00320     p_sys->i_image = GETINT16(p_buffer);
00321 
00322     if( p_sys->i_image != i_expected_image )
00323     {
00324         msg_Warn( p_dec, "expected subtitle image %u but found %u",
00325                   i_expected_image, p_sys->i_image );
00326     }
00327 
00328     if( i_packet != i_expected_packet )
00329     {
00330         msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
00331                   i_expected_packet, i_packet );
00332     }
00333 
00334     p_block->p_buffer += SPU_HEADER_LEN;
00335     p_block->i_buffer -= SPU_HEADER_LEN;
00336 
00337     p_sys->i_packet = i_packet;
00338     /* First packet in the subtitle block */
00339     if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
00340 
00341     block_ChainAppend( &p_sys->p_spu, p_block );
00342 
00343     if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
00344     {
00345         block_t *p_spu = block_ChainGather( p_sys->p_spu );
00346 
00347         if( p_spu->i_buffer != p_sys->i_spu_size )
00348         {
00349             msg_Warn( p_dec, "subtitle packets size=%d should be %d",
00350                       p_spu->i_buffer, p_sys->i_spu_size );
00351         }
00352 
00353         dbg_print( (DECODE_DBG_PACKET),
00354                  "subtitle packet complete, size=%d", p_spu->i_buffer );
00355 
00356         p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
00357         p_sys->p_spu = 0;
00358         return p_spu;
00359     }
00360 
00361     return NULL;
00362 }
00363 
00364 /******************************************************************************
00365   The format is roughly as follows (everything is big-endian):
00366  
00367    size     description
00368    -------------------------------------------
00369    byte     subtitle channel (0..7) in bits 0-3 
00370    byte     subtitle packet number of this subtitle image 0-N,
00371             if the subtitle packet is complete, the top bit of the byte is 1.
00372    u_int16  subtitle image number
00373    u_int16  length in bytes of the rest
00374    byte     option flags, unknown meaning except bit 3 (0x08) indicates
00375             presence of the duration field
00376    byte     unknown 
00377    u_int32  duration in 1/90000ths of a second (optional), start time
00378             is as indicated by the PTS in the PES header
00379    u_int32  xpos
00380    u_int32  ypos
00381    u_int32  width (must be even)
00382    u_int32  height (must be even)
00383    byte[16] palette, 4 palette entries, each contains values for
00384             Y, U, V and transparency, 0 standing for transparent
00385    byte     command,
00386             cmd>>6==1 indicates shift
00387             (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
00388    u_int32  shift duration in 1/90000ths of a second
00389    u_int16  offset of odd-numbered scanlines - subtitle images are 
00390             given in interlace order
00391    byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
00392             2-bits per palette number
00393 ******************************************************************************/
00394 static void ParseHeader( decoder_t *p_dec, block_t *p_block )
00395 {
00396     decoder_sys_t *p_sys = p_dec->p_sys;
00397     uint8_t *p = p_block->p_buffer;
00398     uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
00399     int i;
00400 
00401     p_sys->i_spu_size = GETINT16(p);
00402     i_options  = *p++;
00403     i_options2 = *p++;
00404 
00405     if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
00406     else p_sys->i_duration = 0; /* Ephemer subtitle */
00407     p_sys->i_duration *= 100 / 9;
00408 
00409     p_sys->i_x_start = GETINT16(p);
00410     p_sys->i_y_start = GETINT16(p);
00411     p_sys->i_width   = GETINT16(p);
00412     p_sys->i_height  = GETINT16(p);
00413 
00414     for( i = 0; i < 4; i++ )
00415     {
00416         p_sys->p_palette[i][0] = *p++; /* Y */
00417         p_sys->p_palette[i][2] = *p++; /* Cr / V */
00418         p_sys->p_palette[i][1] = *p++; /* Cb / U */
00419         p_sys->p_palette[i][3] = *p++; /* T */
00420     }
00421 
00422     i_cmd = *p++;
00423     /* We do not really know this, FIXME */
00424     if( i_cmd ) {i_cmd_arg = GETINT32(p);}
00425 
00426     /* Actually, this is measured against a different origin, so we have to
00427      * adjust it */
00428     p_sys->second_field_offset = GETINT16(p);
00429     p_sys->i_image_offset  = p - p_block->p_buffer;
00430     p_sys->i_image_length  = p_sys->i_spu_size - p_sys->i_image_offset;
00431     p_sys->metadata_length = p_sys->i_image_offset;
00432 
00433   if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) 
00434   {
00435       msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
00436                "spu size: %d, duration: %lu (d:%d p:%d)",
00437                p_sys->i_x_start, p_sys->i_y_start, 
00438                p_sys->i_width, p_sys->i_height, 
00439                p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
00440                p_sys->i_image_length, p_sys->i_image_offset);
00441       
00442       for( i = 0; i < 4; i++ )
00443       {
00444           msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
00445                    p_sys->p_palette[i][3], p_sys->p_palette[i][0], 
00446                    p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
00447       }
00448   }
00449 }
00450 
00451 /*****************************************************************************
00452  * DecodePacket: parse and decode an subtitle packet
00453  *****************************************************************************
00454  * This function parses and decodes an SPU packet and, if valid, returns a
00455  * subpicture.
00456  *****************************************************************************/
00457 static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
00458 {
00459     decoder_sys_t *p_sys = p_dec->p_sys;
00460     subpicture_t  *p_spu;
00461     subpicture_region_t *p_region;
00462     video_format_t fmt;
00463     int i;
00464 
00465     /* Allocate the subpicture internal data. */
00466     p_spu = p_dec->pf_spu_buffer_new( p_dec );
00467     if( !p_spu ) return NULL;
00468 
00469     p_spu->i_x = p_sys->i_x_start;
00470     p_spu->i_y = p_sys->i_y_start;
00471     p_spu->i_start = p_data->i_pts;
00472     p_spu->i_stop  = p_data->i_pts + p_sys->i_duration;
00473     p_spu->b_ephemer = VLC_TRUE;
00474 
00475     /* Create new subtitle region */
00476     memset( &fmt, 0, sizeof(video_format_t) );
00477     fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
00478 
00487     fmt.i_aspect = VOUT_ASPECT_FACTOR;
00488 
00489     fmt.i_width = fmt.i_visible_width = p_sys->i_width;
00490     fmt.i_height = fmt.i_visible_height = p_sys->i_height;
00491     fmt.i_x_offset = fmt.i_y_offset = 0;
00492     p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
00493     if( !p_region )
00494     {
00495         msg_Err( p_dec, "cannot allocate SVCD subtitle region" );
00496         //goto error;
00497     }
00498 
00499     p_region->fmt.i_aspect = VOUT_ASPECT_FACTOR;
00500     
00501     p_spu->p_region = p_region;
00502     p_region->i_x = p_region->i_y = 0;
00503 
00504     /* Build palette */
00505     fmt.p_palette->i_entries = 4;
00506     for( i = 0; i < fmt.p_palette->i_entries; i++ )
00507     {
00508         fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
00509         fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
00510         fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
00511         fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
00512     }
00513 
00514     SVCDSubRenderImage( p_dec, p_data, p_region );
00515 
00516     return p_spu;
00517 }
00518 
00519 /*****************************************************************************
00520  * SVCDSubRenderImage: reorders bytes of image data in subpicture region.
00521  *****************************************************************************
00522 
00523  The image is encoded using two bits per pixel that select a palette
00524  entry except that value 0 starts a limited run-length encoding for
00525  color 0.  When 0 is seen, the next two bits encode one less than the
00526  number of pixels, so we can encode run lengths from 1 to 4. These get
00527  filled with the color in palette entry 0.
00528 
00529  The encoding of each line is padded to a whole number of bytes.  The
00530  first field is padded to an even byte length and the complete subtitle
00531  is padded to a 4-byte multiple that always include one zero byte at
00532  the end.
00533 
00534  However we'll transform this so that that the RLE is expanded and
00535  interlacing will also be removed.
00536  *****************************************************************************/
00537 static void SVCDSubRenderImage( decoder_t *p_dec, block_t *p_data,
00538                                 subpicture_region_t *p_region )
00539 {
00540     decoder_sys_t *p_sys = p_dec->p_sys;
00541     uint8_t *p_dest = p_region->picture.Y_PIXELS;
00542     int i_field;            /* The subtitles are interlaced */
00543     int i_row, i_column;    /* scanline row/column number */
00544     uint8_t i_color, i_count;
00545     bs_t bs;
00546 
00547     bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
00548              p_data->i_buffer - p_sys->i_image_offset );
00549 
00550     for( i_field = 0; i_field < 2; i_field++ )
00551     {
00552         for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
00553         {
00554             for( i_column = 0; i_column < p_sys->i_width; i_column++ )
00555             {
00556                 i_color = bs_read( &bs, 2 );
00557                 if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
00558                 {
00559                     i_count = __MIN( i_count, p_sys->i_width - i_column );
00560                     memset( &p_dest[i_row * p_region->picture.Y_PITCH +
00561                                     i_column], 0, i_count + 1 );
00562                     i_column += i_count;
00563                     continue;
00564                 }
00565 
00566                 p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
00567             }
00568 
00569             bs_align( &bs );
00570         }
00571 
00572         /* odd field */
00573         bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
00574                  p_sys->second_field_offset,
00575                  p_data->i_buffer - p_sys->i_image_offset -
00576                  p_sys->second_field_offset );
00577     }
00578 }

Generated on Tue Dec 20 10:14:30 2005 for vlc-0.8.4a by  doxygen 1.4.2