]> git.sesse.net Git - vlc/blobdiff - modules/codec/ogt/cvd_parse.c
* ALL: separation of the SPU engine from the VOUT.
[vlc] / modules / codec / ogt / cvd_parse.c
index 5af4107265068e65c55d12783bb3c6441988f99a..289619729dafefdd653f202cf1828c9fcd67e8b1 100644 (file)
@@ -2,7 +2,7 @@
  * parse.c: Philips OGT (SVCD subtitle) packet parser
  *****************************************************************************
  * Copyright (C) 2003, 2004 VideoLAN
- * $Id: cvd_parse.c,v 1.6 2004/01/04 04:56:21 rocky Exp $
+ * $Id$
  *
  * Authors: Rocky Bernstein 
  *   based on code from: 
@@ -55,12 +55,12 @@ static int  ParseImage         ( decoder_t *, subpicture_t * );
   origin. Thus, this is the result of reading some code whose
   correctness is not known and some experimentation.
   
-  CVD subtitles are different in severl ways from SVCD OGT subtitles.
-  First, the image comes first and the metadata is at the end.  So
-  that the metadata can be found easily, the subtitle packet starts
-  with two bytes (everything is big-endian again) that give the total
-  size of the subtitle data and the offset to the metadata - i.e. size
-  of the image data plus the four bytes at the beginning.
+  CVD subtitles are different in several ways from SVCD OGT subtitles.
+  Image comes first and metadata is at the end.  So that the metadata
+  can be found easily, the subtitle packet starts with two bytes
+  (everything is big-endian again) that give the total size of the
+  subtitle data and the offset to the metadata - i.e. size of the
+  image data plus the four bytes at the beginning.
  
   Image data comes interlaced is run-length encoded.  Each field is a
   four-bit nibble. Each nibble contains a two-bit repeat count and a
@@ -73,17 +73,12 @@ static int  ParseImage         ( decoder_t *, subpicture_t * );
   that the fill-line complete case above is not as described and the
   zero repeat count means fill line.  The sample code never produces
   this, so it may be untested.
-  The metadata section does not follow a fixed pattern, every
-  metadata item consists of a tag byte followed by parameters. In all
-  cases known, the block (including the tag byte) is exactly four
-  bytes in length.  Read the code for the rest.
 */
 
 void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
 {
   decoder_sys_t *p_sys = p_dec->p_sys;
-  u_int8_t *p = p_buffer+1;
+  uint8_t *p = p_buffer+1;
 
   dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET), 
             "header: 0x%02x 0x%02x 0x%02x 0x%02x, 0x%02x, 0x%02x, size: %i",
@@ -100,14 +95,28 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
   p_sys->metadata_offset = GETINT16(p);
   p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_offset;
 
-  p_sys->comp_image_offset = 4;
-  p_sys->comp_image_length = p_sys->metadata_offset - p_sys->comp_image_offset;
+  p_sys->i_image_offset = 4;
+  p_sys->i_image_length = p_sys->metadata_offset - p_sys->i_image_offset;
   
   dbg_print(DECODE_DBG_PACKET, "total size: %d  image size: %d\n",
-           p_sys->i_spu_size, p_sys->comp_image_length);
+           p_sys->i_spu_size, p_sys->i_image_length);
 
 }
 
+#define ExtractXY(x, y)                    \
+  x = ((p[1]&0x0f)<<6) + (p[2]>>2); \
+  y = ((p[2]&0x03)<<8) + p[3];
+
+
+/* 
+  We parse the metadata information here. 
+
+  Although metadata information does not have to come in a fixed field
+  order, every metadata field consists of a tag byte followed by
+  parameters. In all cases known, the size including tag byte is
+  exactly four bytes in length.
+*/
+
 void E_(ParseMetaInfo)( decoder_t *p_dec  )
 {
   /* last packet in subtitle block. */
@@ -126,33 +135,37 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
     
     switch ( p[0] ) {
       
-    case 0x04: /* Display duration in 1/90000ths of a second */
-      
-      p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
+    case 0x04: /* subtitle duration in 1/90000ths of a second */
+      {
+       mtime_t i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
+       mtime_t i_duration_scale = config_GetInt( p_dec, MODULE_STRING 
+                                    "-duration-scaling" );
+               
+       dbg_print( DECODE_DBG_PACKET, 
+                  "subtitle display duration %lu secs  (scaled %lu secs)", 
+                  (long unsigned int) (i_duration / 90000), 
+                  (long unsigned int) (i_duration * i_duration_scale / 90000)
+                  );
+       p_sys->i_duration = i_duration * i_duration_scale ;
+       break;
+      }
       
-      dbg_print( DECODE_DBG_PACKET, 
-                "subtitle display duration %u", p_sys->i_duration);
-      break;
       
-    case 0x0c: /* Unknown */
+    case 0x0c: /* unknown */
       dbg_print( DECODE_DBG_PACKET, 
                 "subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x\n",
                 p[0], p[1], p[2], p[3]);
       break;
       
-    case 0x17: /* Position */
-      p_sys->i_x_start = ((p[1]&0x0f)<<6) + (p[2]>>2);
-      p_sys->i_y_start = ((p[2]&0x03)<<8) + p[3];
-      dbg_print( DECODE_DBG_PACKET, 
-                "start position (%d,%d): %.2x %.2x %.2x", 
-                p_sys->i_x_start, p_sys->i_y_start,
-                p[1], p[2], p[3] );
+    case 0x17: /* coordinates of subtitle upper left x, y position */
+      ExtractXY(p_sys->i_x_start, p_sys->i_y_start);
       break;
       
-    case 0x1f: /* Coordinates of the image bottom right */
+    case 0x1f: /* coordinates of subtitle bottom right x, y position */
       {
-       int lastx = ((p[1]&0x0f)<<6) + (p[2]>>2);
-       int lasty = ((p[2]&0x03)<<8) + p[3];
+       int lastx;
+       int lasty;
+       ExtractXY(lastx, lasty);
        p_sys->i_width  = lastx - p_sys->i_x_start + 1;
        p_sys->i_height = lasty - p_sys->i_y_start + 1;
        dbg_print( DECODE_DBG_PACKET, 
@@ -208,7 +221,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
       p_sys->p_palette[3].s.t = p[2] >> 4;
       
       dbg_print( DECODE_DBG_PACKET,
-                "transparancy for primary palette 0..3: "
+                "transparency for primary palette 0..3: "
                 "0x%0x 0x%0x 0x%0x 0x%0x",
                 p_sys->p_palette[0].s.t,
                 p_sys->p_palette[1].s.t,
@@ -225,7 +238,7 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
       p_sys->p_palette_highlight[3].s.t = p[1] >> 4;
       
       dbg_print( DECODE_DBG_PACKET,
-                "transparancy for primary palette 0..3: "
+                "transparency for primary palette 0..3: "
                 "0x%0x 0x%0x 0x%0x 0x%0x",
                 p_sys->p_palette_highlight[0].s.t,
                 p_sys->p_palette_highlight[1].s.t,
@@ -235,19 +248,19 @@ void E_(ParseMetaInfo)( decoder_t *p_dec  )
       break;
       
     case 0x47:
-      /* offset to first field data, we correct to make it relative
-        to comp_image_offset (usually 4) */
+      /* offset to start of even rows of interlaced image, we correct
+        to make it relative to i_image_offset (usually 4) */
       p_sys->first_field_offset =
-       (p[2] << 8) + p[3] - p_sys->comp_image_offset;
+       (p[2] << 8) + p[3] - p_sys->i_image_offset;
       dbg_print( DECODE_DBG_PACKET, 
                 "first_field_offset %d", p_sys->first_field_offset);
       break;
       
     case 0x4f:
-      /* offset to second field data, we correct to make it relative to
-        comp_image_offset (usually 4) */
+      /* offset to start of odd rows of interlaced image, we correct
+        to make it relative to i_image_offset (usually 4) */
       p_sys->second_field_offset =
-       (p[2] << 8) + p[3] - p_sys->comp_image_offset;
+       (p[2] << 8) + p[3] - p_sys->i_image_offset;
       dbg_print( DECODE_DBG_PACKET, 
                 "second_field_offset %d", p_sys->second_field_offset);
       break;
@@ -279,11 +292,10 @@ E_(ParsePacket)( decoder_t *p_dec)
     dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
 
     /* Allocate the subpicture internal data. */
-    p_spu = vout_CreateSubPicture( p_sys->p_vout, MEMORY_SUBPICTURE );
-    if( p_spu == NULL )
-    {
-        return;
-    }
+    p_spu = spu_CreateSubpicture( p_sys->p_vout->p_spu );
+    if( p_spu == NULL ) return;
+
+    p_spu->i_channel = p_sys->i_subpic_channel;
 
     /* In ParseImage we expand the run-length encoded color 0's; also
        we expand pixels and remove the color palette. This should
@@ -295,21 +307,31 @@ E_(ParsePacket)( decoder_t *p_dec)
     /* Fill the p_spu structure */
     vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
 
-    p_spu->pf_render  = VCDSubRender;
+    p_spu->pf_render  = VCDSubBlend;
     p_spu->pf_destroy = VCDSubDestroySPU;
     p_spu->p_sys->p_data = (uint8_t*)p_spu->p_sys + sizeof( subpicture_sys_t );
 
     p_spu->p_sys->i_x_end        = p_sys->i_x_start + p_sys->i_width - 1;
     p_spu->p_sys->i_y_end        = p_sys->i_y_start + p_sys->i_height - 1;
 
+    p_spu->i_x        = p_sys->i_x_start 
+      + config_GetInt( p_dec, MODULE_STRING "-horizontal-correct" );
+
+    p_spu->p_sys->p_palette[0] = p_sys->p_palette[0];
+    p_spu->p_sys->p_palette[1] = p_sys->p_palette[1];
+    p_spu->p_sys->p_palette[2] = p_sys->p_palette[2];
+    p_spu->p_sys->p_palette[3] = p_sys->p_palette[3];
+
     /* FIXME: use aspect ratio for x? */
-    p_spu->i_x        = p_sys->i_x_start * 3 / 4; 
-    p_spu->i_y        = p_sys->i_y_start;
+    p_spu->i_x        = (p_spu->i_x * 3) / 4; 
+    p_spu->i_y        = p_sys->i_y_start 
+      + config_GetInt( p_dec, MODULE_STRING "-vertical-correct" );
+
     p_spu->i_width    = p_sys->i_width;
     p_spu->i_height   = p_sys->i_height;
 
     p_spu->i_start    = p_sys->i_pts;
-    p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration * 5);
+    p_spu->i_stop     = p_sys->i_pts + (p_sys->i_duration);
     
     p_spu->p_sys->b_crop  = VLC_FALSE;
     p_spu->p_sys->i_debug = p_sys->i_debug;
@@ -325,12 +347,12 @@ E_(ParsePacket)( decoder_t *p_dec)
     if( ParseImage( p_dec, p_spu ) )
     {
         /* There was a parse error, delete the subpicture */
-        vout_DestroySubPicture( p_sys->p_vout, p_spu );
+        spu_DestroySubpicture( p_sys->p_vout->p_spu, p_spu );
         return;
     }
 
     /* SPU is finished - we can ask the video output to display it */
-    vout_DisplaySubPicture( p_sys->p_vout, p_spu );
+    spu_DisplaySubpicture( p_sys->p_vout->p_spu, p_spu );
 
 }
 
@@ -408,8 +430,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
     uint8_t i_pending = 0;     /* number of pixels to fill with 
                                  color zero 0..3 */
     ogt_color_t i_color=0;     /* current pixel color: 0..3 */
-    uint8_t *p = p_sys->subtitle_data  + p_sys->comp_image_offset;
-    uint8_t *maxp = p + p_sys->comp_image_length;
+    uint8_t *p = p_sys->subtitle_data  + p_sys->i_image_offset;
+    uint8_t *maxp = p + p_sys->i_image_length;
 
     dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d",
               i_width, i_height);
@@ -517,17 +539,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
     }
 #endif /*HAVE_LIBPNG*/
 
+    VCDSubHandleScaling( p_spu, p_dec );
 
-    VCDInlinePalette( p_dest, p_sys, i_height, i_width );
-
-    /* The video is automatically scaled. However subtitle bitmaps
-       assume a 1:1 aspect ratio. So we need to scale to compensate for
-       or undo the effects of video output scaling. 
-    */
-    /* FIXME do the right scaling depending on vout. It may not be 4:3 */
-    VCDSubScaleX( p_dec, p_spu, 3, 4 );
-
-    /* To be finished...*/
     return VLC_SUCCESS;
 
 }