cvd: bitmap extraction further completed - not fully done.
authorRocky Bernstein <rocky@videolan.org>
Mon, 29 Dec 2003 04:47:44 +0000 (04:47 +0000)
committerRocky Bernstein <rocky@videolan.org>
Mon, 29 Dec 2003 04:47:44 +0000 (04:47 +0000)
ogt_parse.c, render.c: go back to 4-bit alpha since that's what DVD
and CVD have.

modules/codec/ogt/cvd.c
modules/codec/ogt/cvd_parse.c
modules/codec/ogt/ogt_parse.c
modules/codec/ogt/render.c

index 8f008ae..679675f 100644 (file)
@@ -2,7 +2,7 @@
  * cvd.c : CVD Subtitle decoder thread
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: cvd.c,v 1.2 2003/12/28 11:26:52 rocky Exp $
+ * $Id: cvd.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
  *
  * Authors: Rocky Bernstein
  *   based on code from:
@@ -231,6 +231,9 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
               p_buffer[5], p_buffer[6],
               p_block->i_buffer);
 
+    if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[0] )
+      return NULL;
+
     /* There is little data on the format, but it does not seem to have a
        good way to detect the first packet in the subtitle.  It seems,
        however, that it has a valid pts while later packets for the same
index 4dde2e9..3f469e1 100644 (file)
@@ -2,7 +2,7 @@
  * parse.c: Philips OGT (SVCD subtitle) packet parser
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: cvd_parse.c,v 1.2 2003/12/28 11:26:52 rocky Exp $
+ * $Id: cvd_parse.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
  *
  * Authors: Rocky Bernstein 
  *   based on code from: 
@@ -181,32 +181,30 @@ E_(ParsePacket)( decoder_t *p_dec)
 
 }
 
-/* Advance pointer to image pointer, update internal i_remaining counter
-   and check that we haven't goine too far  in the image data. */
-#define advance_color_pointer_byte                                     \
+#define advance_color_byte_pointer                                     \
   p++;                                                                 \
-  i_remaining=4;                                                       \
+  i_remaining = 2;                                                     \
+  /*                                                                   \
+   * This is wrong, it may exceed maxp if it is the last, check                \
+   * should be moved to use location or the algorithm changed to       \
+   * that in vob2sub                                                   \
+  */                                                                   \
   if (p >= maxp) {                                                     \
     msg_Warn( p_dec,                                                   \
-             "broken subtitle - tried to access beyond end "           \
-             "in image extraction");                                   \
+             "broken subtitle - overflow while decoding "              \
+             " padding (%d,%d,%d)\n",                                  \
+             i_field, i_row, i_column );                               \
     return VLC_EGENERIC;                                               \
-  }                                                                    \
-
-#define advance_color_pointer                                          \
-  i_remaining--;                                                       \
-  if ( i_remaining == 0 ) {                                            \
-    advance_color_pointer_byte;                                                \
   }                                                                    
 
 /* Get the next field - either a palette index or a RLE count for
    color 0.  To do this we use byte image pointer p, and i_remaining
    which indicates where we are in the byte.
 */
-static inline ogt_color_t 
+static inline uint8_t
 ExtractField(uint8_t *p, unsigned int i_remaining) 
 {
-  return ( ( *p >> 2*(i_remaining-1) ) & 0x3 );
+  return ( ( *p >> 4*(i_remaining-1) ) & 0xf );
 }
 
 /*****************************************************************************
@@ -215,20 +213,22 @@ ExtractField(uint8_t *p, unsigned int i_remaining)
  This part parses the subtitle graphical data and stores it in a more
  convenient structure for later rendering. 
 
- The image is encoded using two bits per pixel that select a palette
- entry except that value 0 starts a limited run-length encoding for
- color 0.  When 0 is seen, the next two bits encode one less than the
- number of pixels, so we can encode run lengths from 1 to 4. These get
- filled with the color in palette entry 0.
-
- The encoding of each line is padded to a whole number of bytes.  The
- first field is padded to an even byte length and the complete subtitle
- is padded to a 4-byte multiple that always include one zero byte at
- the end.
+ Image data comes interlaced and is run-length encoded (RLE). Each
+ field is a four-bit nibbles that is further subdivided in a two-bit
+ repeat count and a two-bit color number - up to three pixels can be
+ described in four bits.  What a 0 repeat count means is unknown.  It
+ might be used for RLE extension.  There is a special case of a 0
+ repeat count though.  When the full nibble is zero, the rest of the
+ line is filled with the color value in the next nibble.  It is
+ unknown what happens if the color value is greater than three.  The
+ rest seems to use a 4-entries palette.  It is not impossible 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.
 
  However we'll transform this so that that the RLE is expanded and
  interlacing will also be removed. On output each pixel entry will by 
- an 8-bit alpha, y, u, and v entry.
+ a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
 
  *****************************************************************************/
 static int 
@@ -236,9 +236,108 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
 {
     decoder_sys_t *p_sys = p_dec->p_sys;
 
-    dbg_print( (DECODE_DBG_CALL) , "");
+    unsigned int i_field;  /* The subtitles are interlaced, are we on an
+                             even or odd scanline?  */
+
+    unsigned int i_row;    /* scanline row number */
+    unsigned int i_column; /* scanline column number */
+
+    unsigned int i_width  = p_sys->i_width;
+    unsigned int i_height = p_sys->i_height;
+
+    uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
+
+    uint8_t i_remaining;       /* number of 2-bit pixels remaining 
+                                 in byte of *p */
+    vlc_bool_t b_filling;      /* Filling i_color to the of the line. */
+    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;
+
+    dbg_print( (DECODE_DBG_CALL) , "width x height: %dx%d ",
+              i_width, i_height);
+
+    if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)    
+      printf("\n");
+
+    i_pending = 0;
+
+    for ( i_field=0; i_field < 2; i_field++ ) {
+      i_remaining = 2;  /* 4-bit pieces available in *p */
+      b_filling   = VLC_FALSE;
+
+      for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
+       for ( i_column=0; i_column<i_width; i_column++ ) {
+         if ( i_pending ) {
+           /* We are in the middle of a RLE expansion, just decrement and 
+              fall through with current color value */
+           i_pending--;
+         } else if ( b_filling ) {
+           /* We are just filling to the end of line with one color, just
+              reuse current color value */
+         } else {
+           uint8_t i_val = ExtractField(p, i_remaining--);
+           if ( i_remaining == 0 ) {
+             advance_color_byte_pointer;
+           }
+           if ( i_val == 0 ) {
+             /* fill the rest of the line with next color */
+             i_color = ExtractField( p, i_remaining-- );
+             if ( i_remaining == 0 ) {
+               p++;
+               i_remaining=2;
+               /*
+                 This is wrong, it may exceed maxp if it is the
+                 last, check should be moved to use location or the
+                 algorithm changed to that in vob2sub
+               */
+               if (p >= maxp) {
+                 msg_Warn( p_dec, 
+                           "broken subtitle - overflow while decoding "
+                           " filling (%d,%d,%d)", 
+                             i_field, i_row, i_column);
+                 /* return VLC_EGENERIC; */
+               }
+             }
+             b_filling = VLC_TRUE;
+           } else {
+             /* Normal case: get color and repeat count, 
+                this iteration will  output the first (or only) 
+                instance */
+             i_pending = (i_val >> 2);
+             i_color = i_val & 0x3;
+             /* This time counts against the total */
+             i_pending--;
+           }
+         }
+         /* Color is 0-3. */
+         p_dest[i_row*i_width+i_column] = i_color;
+         
+         if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)       
+           printf("%1d", i_color);
+         
+       }
+       
+       if ( i_remaining != 0 && i_remaining !=2 ) {
+         advance_color_byte_pointer;
+       }
+
+       if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) 
+         printf("\n");
+      }
+    }
+
+    /* 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_EGENERIC;
+    return VLC_SUCCESS;
 
 }
 
index d12af15..3fcae76 100644 (file)
@@ -2,7 +2,7 @@
  * Philips OGT (SVCD subtitle) packet parser
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: ogt_parse.c,v 1.2 2003/12/28 11:26:52 rocky Exp $
+ * $Id: ogt_parse.c,v 1.3 2003/12/29 04:47:44 rocky Exp $
  *
  * Author: Rocky Bernstein 
  *   based on code from: 
@@ -107,10 +107,11 @@ void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
     p_sys->pi_palette[i].s.y = *p++;
     p_sys->pi_palette[i].s.u = *p++;
     p_sys->pi_palette[i].s.v = *p++;
-    /* Note alpha is 8 bits. DVD's use only 4 bits. Our rendering routine
-       will use an 8-bit transparancy.
+    /* OGT has 8-bit resolution for alpha, but DVD's and CVDS use 4-bits.
+       Since we want to use the same render routine, rather than scale up
+       CVD (and DVD) subtitles, we'll scale down ours. 
     */
-    p_sys->pi_palette[i].s.t = *p++;
+    p_sys->pi_palette[i].s.t = (*p++) >> 4;
   }
   p_sys->i_cmd = *p++;
       /* We do not really know this, FIXME */
@@ -259,8 +260,8 @@ ExtractField(uint8_t *p, unsigned int i_remaining)
  the end.
 
  However we'll transform this so that that the RLE is expanded and
- interlacing will also be removed. On output each pixel entry will by 
- an 8-bit alpha, y, u, and v entry.
+ interlacing will also be removed. On output each pixel entry will by
+ an 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
 
  *****************************************************************************/
 static int 
@@ -282,7 +283,7 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
     uint8_t i_remaining;           /* number of 2-bit pixels remaining 
                                      in byte of *p */
     uint8_t i_pending_zero = 0;    /* number of pixels to fill with 
-                                     color zero 0..4 */
+                                     color zero 0..3 */
     ogt_color_t i_color;           /* 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;
@@ -299,6 +300,8 @@ ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
        for ( i_column=0; i_column<i_width; i_column++ ) {
 
          if ( i_pending_zero ) {
+           /* We are in the middle of a RLE expansion, just decrement and 
+              fall through with current color value */
            i_pending_zero--;
            i_color = 0;
          } else {
index 3390275..8b3cbf4 100644 (file)
@@ -2,7 +2,7 @@
  * render.c : Philips OGT (SVCD Subtitle) renderer
  *****************************************************************************
  * Copyright (C) 2003 VideoLAN
- * $Id: render.c,v 1.4 2003/12/28 04:51:52 rocky Exp $
+ * $Id: render.c,v 1.5 2003/12/29 04:47:44 rocky Exp $
  *
  * Author: Rocky Bernstein 
  *   based on code from: 
 #include "subtitle.h"
 #include "render.h"
 
-/* We use 8 bits for an alpha value: 0..255. Note: For DVDs; 0.15. */
-#define ALPHA_BITS (8)
+/* We use 4 bits for an alpha value: 0..15, 15 is completely transparent and
+   0 completely opaque. Note that SVCD allow 8-bits, it should be 
+   scaled down to use these routines.
+*/
+#define ALPHA_BITS (4)
 #define MAX_ALPHA  ((1<<ALPHA_BITS) - 1) 
 
 /* Horrible hack to get dbg_print to do the right thing */