]> git.sesse.net Git - vlc/commitdiff
* modules/codec/cvdsub.c: ported cvd subtitles decoder to the new subpicture architec...
authorGildas Bazin <gbazin@videolan.org>
Sun, 19 Dec 2004 05:05:10 +0000 (05:05 +0000)
committerGildas Bazin <gbazin@videolan.org>
Sun, 19 Dec 2004 05:05:10 +0000 (05:05 +0000)
* modules/codec/svcdsub.c: ported svcd subtitles decoder to the new subpicture architecture.

20 files changed:
configure.ac
modules/codec/Modules.am
modules/codec/cvdsub.c [new file with mode: 0644]
modules/codec/ogt/Modules.am [deleted file]
modules/codec/ogt/common.c [deleted file]
modules/codec/ogt/common.h [deleted file]
modules/codec/ogt/cvd.c [deleted file]
modules/codec/ogt/cvd.h [deleted file]
modules/codec/ogt/cvd_parse.c [deleted file]
modules/codec/ogt/ogt.c [deleted file]
modules/codec/ogt/ogt.h [deleted file]
modules/codec/ogt/ogt_parse.c [deleted file]
modules/codec/ogt/pixmap.c [deleted file]
modules/codec/ogt/pixmap.h [deleted file]
modules/codec/ogt/render.c [deleted file]
modules/codec/ogt/render.h [deleted file]
modules/codec/ogt/subtitle.h [deleted file]
modules/codec/ogt/write_png.c [deleted file]
modules/codec/ogt/write_png.h [deleted file]
modules/codec/svcdsub.c [new file with mode: 0644]

index 851a065b8554be432327550ae83de823c83b691b..108753074935eef61b8dcae32b11f3e933875feb 100644 (file)
@@ -2464,8 +2464,6 @@ AC_CHECK_HEADERS(png.h, [
   AC_CHECK_LIB(png, png_set_rows, [
     VLC_ADD_LDFLAGS([png],[-lpng -lz])
     VLC_ADD_PLUGINS([png])
-    VLC_ADD_LDFLAGS([svcdsub],[-lpng -lz])
-    VLC_ADD_LDFLAGS([cvdsub],[-lpng -lz -lm])
     AC_DEFINE(HAVE_LIBPNG, [], [Define if you have the PNG library: libpng])],
     [],[-lz])
   LDFLAGS="${LDFLAGS_save}"
@@ -4169,7 +4167,6 @@ AC_CONFIG_FILES([
   modules/codec/cmml/Makefile
   modules/codec/dmo/Makefile
   modules/codec/ffmpeg/Makefile
-  modules/codec/ogt/Makefile
   modules/codec/spudec/Makefile
   modules/control/Makefile
   modules/control/corba/Makefile
index 5ada1330eff437d0e64bcdabab9737a41ac6a3ff..c74dbe0f65b62d23f9a1d8667eef840a99a1f0ff 100644 (file)
@@ -23,3 +23,5 @@ SOURCES_x264 = x264.c
 SOURCES_toolame = toolame.c
 SOURCES_dirac = dirac.c
 SOURCES_png = png.c
+SOURCES_svcdsub = svcdsub.c
+SOURCES_cvdsub = cvdsub.c
diff --git a/modules/codec/cvdsub.c b/modules/codec/cvdsub.c
new file mode 100644 (file)
index 0000000..477e99a
--- /dev/null
@@ -0,0 +1,611 @@
+/*****************************************************************************
+ * cvd.c : CVD Subtitle decoder
+ *****************************************************************************
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id$
+ *
+ * Authors: Rocky Bernstein
+ *          Gildas Bazin <gbazin@videolan.org>
+ *          Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
+ *          Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/decoder.h>
+
+#include "vlc_bits.h"
+
+#define DEBUG_CVDSUB 1
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+static int  DecoderOpen   ( vlc_object_t * );
+static int  PacketizerOpen( vlc_object_t * );
+static void DecoderClose  ( vlc_object_t * );
+
+vlc_module_begin();
+    set_description( _("CVD subtitle decoder") );
+    set_capability( "decoder", 50 );
+    set_callbacks( DecoderOpen, DecoderClose );
+
+    add_submodule();
+    set_description( _("Chaoji VCD subtitle packetizer") );
+    set_capability( "packetizer", 50 );
+    set_callbacks( PacketizerOpen, DecoderClose );
+vlc_module_end();
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static subpicture_t *Decode( decoder_t *, block_t ** );
+static block_t *Packetize  ( decoder_t *, block_t ** );
+static block_t *Reassemble ( decoder_t *, block_t * );
+static void ParseMetaInfo  ( decoder_t *, block_t * );
+static void ParseHeader    ( decoder_t *, block_t * );
+static subpicture_t *DecodePacket( decoder_t *, block_t * );
+static void RenderImage( decoder_t *, block_t *, subpicture_region_t * );
+
+#define SUBTITLE_BLOCK_EMPTY 0
+#define SUBTITLE_BLOCK_PARTIAL 1
+#define SUBTITLE_BLOCK_COMPLETE 2
+
+struct decoder_sys_t
+{
+  int      b_packetizer;
+
+  int      i_state;    /* data-gathering state for this subtitle */
+
+  block_t  *p_spu;   /* Bytes of the packet. */
+
+  int     i_spu_size;     /* goal for subtitle_data_pos while gathering,
+                             size of used subtitle_data later */
+
+  uint16_t i_image_offset;      /* offset from subtitle_data to compressed
+                                   image data */
+  int i_image_length;           /* size of the compressed image data */
+  int first_field_offset;       /* offset of even raster lines */
+  int second_field_offset;      /* offset of odd raster lines */
+  int metadata_offset;          /* offset to data describing the image */
+  int metadata_length;          /* length of metadata */
+
+  mtime_t i_duration;   /* how long to display the image, 0 stands
+                           for "until next subtitle" */
+
+  uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
+                                    image when displayed */
+  uint16_t i_width, i_height;    /* dimensions in pixels of image */
+
+  uint8_t p_palette[4][4];       /* Palette of colors used in subtitle */
+  uint8_t p_palette_highlight[4][4];
+};
+
+/*****************************************************************************
+ * DecoderOpen: open/initialize the cvdsub decoder.
+ *****************************************************************************/
+static int DecoderOpen( vlc_object_t *p_this )
+{
+    decoder_t     *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'c','v','d',' ' ) )
+    {
+        return VLC_EGENERIC;
+    }
+
+    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
+
+    p_sys->b_packetizer  = VLC_FALSE;
+
+    p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
+    p_sys->p_spu   = NULL;
+
+    es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'c','v','d',' ' ) );
+
+    p_dec->pf_decode_sub = Decode;
+    p_dec->pf_packetize  = Packetize;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * PacketizerOpen: open/initialize the cvdsub packetizer.
+ *****************************************************************************/
+static int PacketizerOpen( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+
+    if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
+
+    p_dec->p_sys->b_packetizer = VLC_TRUE;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DecoderClose: closes the cvdsub decoder/packetizer.
+ *****************************************************************************/
+void DecoderClose( vlc_object_t *p_this )
+{
+    decoder_t     *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
+    free( p_sys );
+}
+
+/*****************************************************************************
+ * Decode:
+ *****************************************************************************/
+static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
+{
+    block_t *p_block, *p_spu;
+
+    if( pp_block == NULL || *pp_block == NULL ) return NULL;
+
+    p_block = *pp_block;
+    *pp_block = NULL;
+
+    if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
+
+    /* Parse and decode */
+    return DecodePacket( p_dec, p_spu );
+}
+
+/*****************************************************************************
+ * Packetize:
+ *****************************************************************************/
+static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
+{
+    block_t *p_block, *p_spu;
+
+    if( pp_block == NULL || *pp_block == NULL ) return NULL;
+
+    p_block = *pp_block;
+    *pp_block = NULL;
+
+    if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
+
+    p_spu->i_dts = p_spu->i_pts;
+    p_spu->i_length = 0;
+
+    return p_spu;
+}
+
+
+/*****************************************************************************
+ Reassemble:
+
+ Data for single screen subtitle may come in several non-contiguous
+ packets of a stream. This routine is called when the next packet in
+ the stream comes in. The job of this routine is to parse the header,
+ if this is the beginning, and combine the packets into one complete
+ subtitle unit.
+
+ If everything is complete, we will return a block. Otherwise return
+ NULL.
+
+ *****************************************************************************/
+#define SPU_HEADER_LEN 1
+
+static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p_buffer;
+
+    if( p_block->i_buffer < SPU_HEADER_LEN )
+    {
+        msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
+                 p_block->i_buffer, SPU_HEADER_LEN );
+        block_Release( p_block );
+        return NULL;
+    }
+
+    p_buffer = p_block->p_buffer;
+
+    /* From the scant data on the format, there is only only way known
+     * to detect the first packet in a subtitle.  The first packet
+     * seems to have a valid PTS while later packets for the same
+     * image don't. */
+    if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY && p_block->i_pts == 0 )
+    {
+        msg_Warn( p_dec, "first packet expected but no PTS present");
+        return NULL;
+    }
+
+    p_block->p_buffer += SPU_HEADER_LEN;
+    p_block->i_buffer -= SPU_HEADER_LEN;
+
+    /* First packet in the subtitle block */
+    if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY ) ParseHeader( p_dec, p_block );
+
+    block_ChainAppend( &p_sys->p_spu, p_block );
+    p_sys->p_spu = block_ChainGather( p_sys->p_spu );
+
+    if( p_sys->p_spu->i_buffer >= p_sys->i_spu_size )
+    {
+        block_t *p_spu = p_sys->p_spu;
+
+        if( p_spu->i_buffer != p_sys->i_spu_size )
+        {
+            msg_Warn( p_dec, "SPU packets size=%d should be %d",
+                      p_spu->i_buffer, p_sys->i_spu_size );
+        }
+
+        msg_Dbg( p_dec, "subtitle packet complete, size=%d", p_spu->i_buffer);
+
+        ParseMetaInfo( p_dec, p_spu );
+
+        p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
+        p_sys->p_spu = 0;
+        return p_spu;
+    }
+    else
+    {
+        /* Not last block in subtitle, so wait for another. */
+        p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
+    }
+
+    return NULL;
+}
+
+/*
+  We do not have information on the subtitle format used on CVD's
+  except the submux sample code and a couple of samples of dubious
+  origin. Thus, this is the result of reading some code whose
+  correctness is not known and some experimentation.
+  
+  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
+  two-bit color number so that up to three pixels can be described in
+  four bits.  The function of a 0 repeat count is unknown; it might be
+  used for RLE extension.  However 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.
+*/
+
+static void ParseHeader( decoder_t *p_dec, block_t *p_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p = p_block->p_buffer;
+
+    p_sys->i_spu_size = (p[0] << 8) + p[1] + 4; p += 2;
+
+    /* FIXME: check data sanity */
+    p_sys->metadata_offset = (p[0] <<  8) +   p[1]; p +=2;
+    p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_offset;
+
+    p_sys->i_image_offset = 4;
+    p_sys->i_image_length = p_sys->metadata_offset - p_sys->i_image_offset;
+  
+#ifdef DEBUG_CVDSUB
+    msg_Dbg( p_dec, "total size: %d  image size: %d",
+             p_sys->i_spu_size, p_sys->i_image_length );
+#endif
+
+}
+
+/* 
+  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.
+*/
+
+#define ExtractXY(x, y) x = ((p[1]&0x0f)<<6) + (p[2]>>2); \
+                        y = ((p[2]&0x03)<<8) + p[3];
+
+static void ParseMetaInfo( decoder_t *p_dec, block_t *p_spu  )
+{
+    /* Last packet in subtitle block. */
+
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t       *p     = p_spu->p_buffer + p_sys->metadata_offset;
+    uint8_t       *p_end = p + p_sys->metadata_length;
+  
+    for( ; p < p_end; p += 4 )
+    {
+        switch( p[0] )
+        {
+        case 0x04: /* subtitle duration in 1/90000ths of a second */
+            p_sys->i_duration = (p[1]<<16) + (p[2]<<8) + p[3];
+
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "subtitle display duration %lu secs",
+                     (long unsigned int)(p_sys->i_duration / 90000) );
+#endif
+            p_sys->i_duration *= 100 / 9;
+            break;
+      
+        case 0x0c: /* unknown */
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "subtitle command unknown 0x%0x 0x%0x 0x%0x 0x%0x",
+                     (int)p[0], (int)p[1], (int)p[2], (int)p[3] );
+#endif
+            break;
+      
+        case 0x17: /* coordinates of subtitle upper left x, y position */
+            ExtractXY(p_sys->i_x_start, p_sys->i_y_start);
+
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "start position (%d,%d)",
+                     p_sys->i_x_start, p_sys->i_y_start );
+#endif
+            break;
+      
+        case 0x1f: /* coordinates of subtitle bottom right x, y position */
+        {
+            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;
+
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "end position (%d,%d), w x h: %dx%d",
+                     lastx, lasty, p_sys->i_width, p_sys->i_height );
+#endif
+            break;
+        }
+      
+        case 0x24:
+        case 0x25:
+        case 0x26:
+        case 0x27: 
+        {
+            uint8_t v = p[0] - 0x24;
+
+#ifdef DEBUG_CVDSUB
+            /* Primary Palette */
+            msg_Dbg( p_dec, "primary palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
+                     (int)v, (int)p[1], (int)p[2], (int)p[3] );
+#endif
+
+            p_sys->p_palette[v][0] = p[1];
+            p_sys->p_palette[v][1] = p[2];
+            p_sys->p_palette[v][2] = p[3];
+            break;
+        }
+
+        case 0x2c:
+        case 0x2d:
+        case 0x2e:
+        case 0x2f:
+        {
+            uint8_t v = p[0] - 0x2c;
+
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec,"highlight palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
+                     (int)v, (int)p[1], (int)p[2], (int)p[3] );
+#endif
+
+            /* Highlight Palette */
+            p_sys->p_palette_highlight[v][0] = p[1];
+            p_sys->p_palette_highlight[v][1] = p[2];
+            p_sys->p_palette_highlight[v][2] = p[3];
+            break;
+        }
+
+        case 0x37:
+            /* transparency for primary palette */
+            p_sys->p_palette[0][3] = (p[3] & 0x0f) << 4;
+            p_sys->p_palette[1][3] = (p[3] >> 4) << 4;
+            p_sys->p_palette[2][3] = (p[2] & 0x0f) << 4;
+            p_sys->p_palette[3][3] = (p[2] >> 4) << 4;
+
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "transparency for primary palette 0..3: "
+                     "0x%0x 0x%0x 0x%0x 0x%0x",
+                     (int)p_sys->p_palette[0][3], (int)p_sys->p_palette[1][3],
+                     (int)p_sys->p_palette[2][3], (int)p_sys->p_palette[3][3]);
+#endif
+            break;
+      
+        case 0x3f:
+            /* transparency for highlight palette */
+            p_sys->p_palette_highlight[0][3] = (p[2] & 0x0f) << 4;
+            p_sys->p_palette_highlight[1][3] = (p[2] >> 4) << 4;
+            p_sys->p_palette_highlight[2][3] = (p[1] & 0x0f) << 4;
+            p_sys->p_palette_highlight[3][3] = (p[1] >> 4) << 4;
+
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "transparency for highlight palette 0..3: "
+                     "0x%0x 0x%0x 0x%0x 0x%0x",
+                     (int)p_sys->p_palette_highlight[0][3],
+                     (int)p_sys->p_palette_highlight[1][3],
+                     (int)p_sys->p_palette_highlight[2][3],
+                     (int)p_sys->p_palette_highlight[3][3] );
+#endif
+            break;
+
+        case 0x47:
+            /* 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->i_image_offset;
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "1st_field_offset %d", p_sys->first_field_offset );
+#endif
+            break;
+
+        case 0x4f:
+            /* 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->i_image_offset;
+#ifdef DEBUG_CVDSUB
+            msg_Dbg( p_dec, "2nd_field_offset %d", p_sys->second_field_offset);
+#endif
+            break;
+
+        default:
+#ifdef DEBUG_CVDSUB
+            msg_Warn( p_dec, "unknown sequence in control header " 
+                      "0x%0x 0x%0x 0x%0x 0x%0x", p[0], p[1], p[2], p[3]);
+#endif
+        }
+    }
+}
+
+/*****************************************************************************
+ * DecodePacket: parse and decode an SPU packet
+ *****************************************************************************
+ * This function parses and decodes an SPU packet and, if valid, returns a
+ * subpicture.
+ *****************************************************************************/
+static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    subpicture_t  *p_spu;
+    subpicture_region_t *p_region;
+    video_format_t fmt;
+    int i;
+
+    /* Allocate the subpicture internal data. */
+    p_spu = p_dec->pf_spu_buffer_new( p_dec );
+    if( !p_spu ) return NULL;
+
+    p_spu->i_x = p_sys->i_x_start;
+    p_spu->i_x = p_spu->i_x * 3 / 4; /* FIXME: use aspect ratio for x? */
+    p_spu->i_y = p_sys->i_y_start;
+    p_spu->i_start = p_data->i_pts;
+    p_spu->i_stop  = p_data->i_pts + p_sys->i_duration;
+    p_spu->b_ephemer = VLC_TRUE;
+
+    /* Create new SPU region */
+    memset( &fmt, 0, sizeof(video_format_t) );
+    fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
+    fmt.i_aspect = VOUT_ASPECT_FACTOR;
+    fmt.i_width = fmt.i_visible_width = p_sys->i_width;
+    fmt.i_height = fmt.i_visible_height = p_sys->i_height;
+    fmt.i_x_offset = fmt.i_y_offset = 0;
+    p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
+    if( !p_region )
+    {
+        msg_Err( p_dec, "cannot allocate SPU region" );
+        //goto error;
+    }
+
+    p_spu->p_region = p_region;
+    p_region->i_x = p_region->i_y = 0;
+
+    /* Build palette */
+    fmt.p_palette->i_entries = 4;
+    for( i = 0; i < fmt.p_palette->i_entries; i++ )
+    {
+        fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
+        fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
+        fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
+        fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
+    }
+
+    RenderImage( p_dec, p_data, p_region );
+
+    return p_spu;
+}
+
+/*****************************************************************************
+ * ParseImage: parse and render the image part of the subtitle
+ *****************************************************************************
+ This part parses the subtitle graphical data and renders it. 
+
+ 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 
+ a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
+
+ *****************************************************************************/
+static void RenderImage( decoder_t *p_dec, block_t *p_data,
+                         subpicture_region_t *p_region )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p_dest = p_region->picture.Y_PIXELS;
+    int i_field;            /* The subtitles are interlaced */
+    int i_row, i_column;    /* scanline row/column number */
+    uint8_t i_color, i_count;
+    bs_t bs;
+
+    bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
+             p_data->i_buffer - p_sys->i_image_offset );
+
+    for( i_field = 0; i_field < 2; i_field++ )
+    {
+        for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
+        {
+            for( i_column = 0; i_column < p_sys->i_width; i_column++ )
+            {
+                uint8_t i_val = bs_read( &bs, 4 );
+
+                if( i_val == 0 )
+                {
+                    /* Fill the rest of the line with next color */
+                    i_color = bs_read( &bs, 4 );
+
+                    memset( &p_dest[i_row * p_region->picture.Y_PITCH +
+                                    i_column], i_color,
+                            p_sys->i_width - i_column );
+                    i_column = p_sys->i_width;
+                    continue;
+                }
+                else
+                {
+                    /* Normal case: get color and repeat count */
+                    i_count = (i_val >> 2);
+                    i_color = i_val & 0x3;
+
+                    i_count = __MIN( i_count, p_sys->i_width - i_column );
+
+                    memset( &p_dest[i_row * p_region->picture.Y_PITCH +
+                                    i_column], i_color, i_count );
+                    i_column += i_count - 1;
+                    continue;
+                }
+            }
+
+            bs_align( &bs );
+        }
+    }
+}
diff --git a/modules/codec/ogt/Modules.am b/modules/codec/ogt/Modules.am
deleted file mode 100644 (file)
index 4dc261c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-SOURCES_svcdsub = \
-       common.c \
-       common.h \
-       subtitle.h \
-       ogt.c \
-       ogt.h \
-       ogt_parse.c \
-       pixmap.c \
-       pixmap.h \
-       render.c \
-       render.h \
-       write_png.c \
-       write_png.h \
-       $(NULL)
-
-SOURCES_cvdsub = \
-       common.c \
-       common.h \
-       cvd.c \
-       cvd.h \
-       subtitle.h \
-       cvd_parse.c \
-       pixmap.c \
-       pixmap.h \
-       render.c \
-       render.h \
-       write_png.c \
-       write_png.h \
-       $(NULL)
diff --git a/modules/codec/ogt/common.c b/modules/codec/ogt/common.c
deleted file mode 100644 (file)
index e12aebf..0000000
+++ /dev/null
@@ -1,540 +0,0 @@
-/*****************************************************************************
- * Common SVCD and CVD subtitle routines.
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id$
- *
- * Author: Rocky Bernstein <rocky@panix.com>
- *   based on code from:
- *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
- *       Samuel Hocevar <sam@zoy.org>
- *       Laurent Aimar <fenrir@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
-
-#include "subtitle.h"
-#include "pixmap.h"
-#include "common.h"
-#ifdef HAVE_LIBPNG
-#include "write_png.h"
-#endif
-
-/*****************************************************************************
- Free Resources associated with subtitle packet.
- *****************************************************************************/
-void VCDSubClose( vlc_object_t *p_this )
-{
-    decoder_t     *p_dec = (decoder_t*)p_this;
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
-
-    if( !p_sys->b_packetizer && p_sys->p_vout )
-    {
-        /* FIXME check if it's ok to not lock vout */
-        spu_Control( p_sys->p_vout->p_spu, SPU_CHANNEL_CLEAR,
-                     p_sys->i_subpic_channel );
-    }
-
-    if( p_sys->p_block )
-    {
-        block_ChainRelease( p_sys->p_block );
-    }
-
-    free(p_sys->subtitle_data);
-    free( p_sys );
-}
-
-/*****************************************************************************
-
-Initialize so the next packet will start off a new one.
-
- *****************************************************************************/
-void 
-VCDSubInitSubtitleBlock( decoder_sys_t * p_sys ) 
-{
-  p_sys->i_spu_size = 0;
-  p_sys->state      = SUBTITLE_BLOCK_EMPTY;
-  p_sys->i_spu      = 0;
-  p_sys->p_block    = NULL;
-  p_sys->subtitle_data_pos = 0;
-
-}
-
-void 
-VCDSubInitSubtitleData(decoder_sys_t *p_sys)
-{
-  if ( p_sys->subtitle_data ) {
-    if ( p_sys->subtitle_data_size < p_sys->i_spu_size ) {
-      p_sys->subtitle_data = realloc(p_sys->subtitle_data,
-                                   p_sys->i_spu_size);
-      p_sys->subtitle_data_size = p_sys->i_spu_size;
-    }
-  } else {
-    p_sys->subtitle_data = malloc(p_sys->i_spu_size);
-    p_sys->subtitle_data_size = p_sys->i_spu_size;
-    /* FIXME: wrong place to get p_sys */
-    p_sys->i_image = 0;
-  }
-  p_sys->subtitle_data_pos = 0;
-}
-
-void 
-VCDSubAppendData ( decoder_t *p_dec, uint8_t *buffer, uint32_t buf_len )
-{
-  decoder_sys_t *p_sys = p_dec->p_sys;
-  int chunk_length = buf_len;
-
-  if ( chunk_length > p_sys->i_spu_size - p_sys->subtitle_data_pos ) {
-    msg_Warn( p_dec, "too much data (%d) expecting at most %u",
-             chunk_length, p_sys->i_spu_size - p_sys->subtitle_data_pos );
-
-    chunk_length = p_sys->i_spu_size - p_sys->subtitle_data_pos;
-  }
-
-  if ( chunk_length > 0 ) {
-#if 0
-    int i;
-    int8_t *b=buffer;
-    for (i=0; i<chunk_length; i++)
-      printf ("%02x", b[i]);
-    printf("\n");
-#endif
-    
-    memcpy(p_sys->subtitle_data + p_sys->subtitle_data_pos,
-          buffer, chunk_length);
-    p_sys->subtitle_data_pos += chunk_length;
-    dbg_print(DECODE_DBG_PACKET, "%d bytes appended, pointer now %d",
-             chunk_length, p_sys->subtitle_data_pos);
-  }
-}
-
-
-/*****************************************************************************
- * FindVout: Find a vout or wait for one to be created.
- *****************************************************************************/
-vout_thread_t *VCDSubFindVout( decoder_t *p_dec )
-{
-    vout_thread_t *p_vout = NULL;
-
-    /* Find an available video output */
-    do
-    {
-        if( p_dec->b_die || p_dec->b_error )
-        {
-            break;
-        }
-
-        p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE );
-        if( p_vout )
-        {
-            break;
-        }
-
-        msleep( VOUT_OUTMEM_SLEEP );
-    }
-    while( 1 );
-
-    return p_vout;
-}
-
-
-
-/**
-   Remove color palette by expanding pixel entries to contain the
-   palette values. We work from the free space at the end to the
-   beginning so we can expand inline.
-*/
-static void
-InlinePalette ( /*inout*/ uint8_t *p_dest, decoder_sys_t *p_sys )
-{
-  const unsigned int i_width  = p_sys->i_width;
-  const unsigned int i_height = p_sys->i_height;
-  int n = (i_height * i_width) - 1;
-  uint8_t    *p_from = p_dest;
-  ogt_yuvt_t *p_to   = (ogt_yuvt_t *) p_dest;
-  
-  for ( ; n >= 0 ; n-- ) {
-    p_to[n] = p_sys->p_palette[p_from[n]];
-    /*p_to[n] = p_sys->p_palette[p_from[3]];*/
-  }
-}
-
-/**
-   Check to see if user has overridden subtitle aspect ratio. 
-   0 is returned for no override which means just counteract any
-   scaling effects.
-*/
-unsigned int 
-VCDSubGetAROverride(vlc_object_t * p_input, vout_thread_t *p_vout)
-{
-  char *psz_string = config_GetPsz( p_input, MODULE_STRING "-aspect-ratio" );
-
-  /* Check whether the user tried to override aspect ratio */
-  if( !psz_string ) return 0;
-
-  {
-    unsigned int i_new_aspect = 0;
-    char *psz_parser = strchr( psz_string, ':' );
-    
-    if( psz_parser )
-      {
-       *psz_parser++ = '\0';
-       i_new_aspect = atoi( psz_string ) * VOUT_ASPECT_FACTOR
-         / atoi( psz_parser );
-      }
-    else
-      {
-       i_new_aspect = p_vout->output.i_width * VOUT_ASPECT_FACTOR
-         * atof( psz_string )
-         / p_vout->output.i_height;
-      }
-    
-    return i_new_aspect;
-  }
-}
-
-
-/**
-   Scales down (reduces size) of p_dest in the x direction as 
-   determined through aspect ratio x_scale by y_scale. Scaling
-   is done in place. p_spu->i_width, is updated to new width
-
-   The aspect ratio is assumed to be between 1/2 and 1.
-
-   Note: the scaling truncates the new width rather than rounds it.
-   Perhaps something one might want to address.
-*/
-void
-VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu, 
-             unsigned int i_scale_x, unsigned int i_scale_y )
-{
-  int i_row, i_col;
-
-  decoder_sys_t *p_sys = p_dec->p_sys;
-  uint8_t *p_src1 = p_spu->p_sys->p_data;
-  uint8_t *p_src2 = p_src1 + PIXEL_SIZE;
-  uint8_t *p_dst  = p_src1;
-  unsigned int i_new_width = (p_spu->i_width * i_scale_x) / i_scale_y ;
-  unsigned int i_used=0;  /* Number of bytes used up in p_src1. */
-
-  dbg_print( (DECODE_DBG_CALL|DECODE_DBG_TRANSFORM) , 
-            "aspect ratio %i:%i, Old width: %d, new width: %d", 
-            i_scale_x, i_scale_y, p_spu->i_width, i_new_width);
-
-  if (! (i_scale_x < i_scale_y && i_scale_y < i_scale_x+i_scale_x) )
-    {
-      msg_Warn( p_dec, "Need x < y < 2x. x: %i, y: %i", i_scale_x, i_scale_y );
-      return;
-    }
-  
-  for ( i_row=0; i_row <= p_spu->i_height - 1; i_row++ ) {
-
-    if (i_used != 0) {
-      /* Discard the remaining piece of the column of the previous line*/
-      i_used=0;
-      p_src1 = p_src2;
-      p_src2 += PIXEL_SIZE;
-    }
-    
-    for ( i_col=0; i_col <= p_spu->i_width - 2; i_col++ ) {
-      unsigned int i;
-      unsigned int w1= i_scale_x - i_used;
-      unsigned int w2;
-      
-      if ( i_scale_y - w1 <= i_scale_x ) {
-       /* Average spans 2 pixels. */
-       w2 = i_scale_y - w1;
-
-       for (i = 0; i < PIXEL_SIZE; i++ ) {
-         *p_dst = ( (*p_src1 * w1) + (*p_src2 * w2) ) / i_scale_y;
-         p_src1++; p_src2++; p_dst++;
-       }
-      } else {
-       /* Average spans 3 pixels. */
-       unsigned int w0 = w1;
-       unsigned int w1 = i_scale_x;
-       uint8_t *p_src0 = p_src1;
-       w2 = i_scale_y - w0 - w1;
-       p_src1 = p_src2;
-       p_src2 += PIXEL_SIZE;
-       
-       for (i = 0; i < PIXEL_SIZE; i++ ) {
-         *p_dst = ( (*p_src0 * w0) + (*p_src1 * w1) + (*p_src2 * w2) ) 
-                    / i_scale_y;
-         p_src0++; p_src1++; p_src2++; p_dst++;
-       }
-       i_col++;
-      }
-
-      i_used = w2;
-
-      if (i_scale_x == i_used) {
-       /* End of last pixel was end of p_src2. */
-       p_src1 = p_src2;
-       p_src2 += PIXEL_SIZE;
-       i_col++;
-       i_used = 0;
-      }
-    }
-  }
-  p_spu->i_width = i_new_width;
-
-  if ( p_sys && p_sys->i_debug & DECODE_DBG_TRANSFORM )
-  { 
-    ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
-    for ( i_row=0; i_row < p_spu->i_height; i_row++ ) {
-      for ( i_col=0; i_col < p_spu->i_width; i_col++ ) {
-       printf("%1x", p_source->s.t);
-       p_source++;
-      }
-      printf("\n");
-    }
-  }
-
-}
-
-/**
-   The video may be scaled. However subtitle bitmaps assume an 1:1
-   aspect ratio. So unless the user has specified otherwise, we
-   need to scale to compensate for or undo the effects of video
-   output scaling.
-   
-   Perhaps this should go in the Render routine? The advantage would
-   be that it will deal with a dynamically changing aspect ratio.
-   The downside is having to scale many times for each render call.
-
-   We also expand palette entries here, unless we are dealing with a 
-   palettized chroma (e.g. RGB2).
-*/
-
-void 
-VCDSubHandleScaling( subpicture_t *p_spu, decoder_t *p_dec )
-{
-  vlc_object_t * p_input = p_spu->p_sys->p_input;
-  vout_thread_t *p_vout = vlc_object_find( p_input, VLC_OBJECT_VOUT, 
-                                           FIND_CHILD );
-  int i_aspect_x, i_aspect_y;
-  uint8_t *p_dest = (uint8_t *)p_spu->p_sys->p_data;
-
-  if (p_vout) {
-    /* Check for user-configuration override. */
-    unsigned int i_new_aspect;
-    
-    if ( p_vout->output.i_chroma == VLC_FOURCC('R','G','B','2') ) {
-      /* This is an unscaled palettized format. We don't allow 
-         user scaling here. And to make the render process faster,
-         we don't expand the palette entries into a color value.
-       */
-      return;
-    }
-        
-    InlinePalette( p_dest, p_dec->p_sys );
-    i_new_aspect = VCDSubGetAROverride( p_input, p_vout );
-
-    if (i_new_aspect == VOUT_ASPECT_FACTOR) {
-      /* For scaling 1:1, nothing needs to be done. Note this means
-         subtitles will get scaled the same way the video does.
-      */
-      ;
-    } else {
-      if (0 == i_new_aspect) {
-        /* Counteract the effects of background video scaling when
-           there is scaling. That's why x and y are reversed from
-           the else branch in the call below.
-        */
-        switch( p_vout->output.i_chroma )
-          {
-            /* chromas in which scaling is done outside of our
-               blending routine, so we need to compensate for those
-               effects before blending gets called: */
-          case VLC_FOURCC('I','4','2','0'):
-          case VLC_FOURCC('I','Y','U','V'):
-          case VLC_FOURCC('Y','V','1','2'):
-          case VLC_FOURCC('Y','U','Y','2'):
-            break;
-            
-            /* chromas in which scaling is done in our blending 
-               routine and thus we don't do it here: */
-          case VLC_FOURCC('R','V','1','6'):
-          case VLC_FOURCC('R','V','2','4'):
-          case VLC_FOURCC('R','V','3','2'):
-          case VLC_FOURCC('R','G','B','2'):
-            return;
-            break;
-            
-          default:
-            msg_Err( p_vout, "unknown chroma %x", 
-                     p_vout->output.i_chroma );
-            return;
-            break;
-          }
-        /* We get here only for scaled chromas. */
-        vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
-                    VOUT_ASPECT_FACTOR, 0 );
-      } else {
-        /* User knows best? */
-        vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
-                    VOUT_ASPECT_FACTOR, 0 );
-      }
-      VCDSubScaleX( p_dec, p_spu, i_aspect_x, i_aspect_y );
-    }
-  }
-}
-
-
-/**
- * DestroySPU: subpicture destructor
- */
-void VCDSubDestroySPU( subpicture_t *p_spu )
-{
-    if( p_spu->p_sys->p_input )
-    {
-        /* Detach from our input thread */
-        vlc_object_release( p_spu->p_sys->p_input );
-    }
-
-    vlc_mutex_destroy( &p_spu->p_sys->lock );
-    free( p_spu->p_sys );
-}
-
-/*****************************************************************************
-  This callback is called from the input thread when we need cropping
- *****************************************************************************/
-int VCDSubCropCallback( vlc_object_t *p_object, char const *psz_var,
-                         vlc_value_t oldval, vlc_value_t newval, void *p_data )
-{
-    VCDSubUpdateSPU( (subpicture_t *)p_data, p_object );
-
-    return VLC_SUCCESS;
-}
-
-
-/*****************************************************************************
-  update subpicture settings
- *****************************************************************************
-  This function is called from CropCallback and at initialization time, to
-  retrieve crop information from the input.
- *****************************************************************************/
-void VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object )
-{
-    vlc_value_t val;
-
-    p_spu->p_sys->b_crop = val.b_bool;
-    if( !p_spu->p_sys->b_crop )
-    {
-        return;
-    }
-
-    if ( VLC_SUCCESS == var_Get( p_object, "x-start", &val ) )
-      p_spu->p_sys->i_x_start = val.i_int;
-    if ( VLC_SUCCESS == var_Get( p_object, "y-start", &val ) )
-      p_spu->p_sys->i_y_start = val.i_int;
-    if ( VLC_SUCCESS == var_Get( p_object, "x-end", &val ) )
-      p_spu->p_sys->i_x_end = val.i_int;
-    if ( VLC_SUCCESS == var_Get( p_object, "y-end", &val ) )
-      p_spu->p_sys->i_y_end = val.i_int;
-
-}
-
-/* 
-   Dump an a subtitle image to standard output - for debugging.
- */
-void VCDSubDumpImage( uint8_t *p_image, uint32_t i_height, uint32_t i_width )
-{
-  uint8_t *p = p_image;
-  unsigned int i_row;    /* scanline row number */
-  unsigned int i_column; /* scanline column number */
-
-  printf("-------------------------------------\n++");
-  for ( i_row=0; i_row < i_height; i_row ++ ) {
-    for ( i_column=0; i_column<i_width; i_column++ ) {
-      printf("%1d", *p++ & 0x03);
-    }
-    printf("\n++");
-  }
-  printf("\n-------------------------------------\n");
-}
-
-#ifdef HAVE_LIBPNG
-
-#define PALETTE_SIZE  4
-/* Note the below assumes the above is a power of 2 */
-#define PALETTE_SIZE_MASK (PALETTE_SIZE-1)
-
-/* 
-   Dump an a subtitle image to a Portable Network Graphics (PNG) file.
-   All we do here is convert YUV palette entries to RGB, expand
-   the image into a linear RGB pixel array, and call the routine
-   that does the PNG writing.
- */
-
-void 
-VCDSubDumpPNG( uint8_t *p_image, decoder_t *p_dec,
-              uint32_t i_height, uint32_t i_width, const char *filename,
-              png_text *text_ptr, int i_text_count )
-{
-  decoder_sys_t *p_sys = p_dec->p_sys;
-  uint8_t *p = p_image;
-  uint8_t *image_data = malloc(RGB_SIZE * i_height * i_width );
-  uint8_t *q = image_data;
-  unsigned int i_row;    /* scanline row number */
-  unsigned int i_column; /* scanline column number */
-  uint8_t rgb_palette[PALETTE_SIZE * RGB_SIZE];
-  int i;
-
-  dbg_print( (DECODE_DBG_CALL), "%s", filename);
-  
-  if (NULL == image_data) return;
-
-  /* Convert palette YUV into RGB. */
-  for (i=0; i<PALETTE_SIZE; i++) {
-    ogt_yuvt_t *p_yuv     = &(p_sys->p_palette[i]);
-    uint8_t   *p_rgb_out  = &(rgb_palette[i*RGB_SIZE]);
-    yuv2rgb( p_yuv, p_rgb_out );
-  }
-  
-  /* Convert palette entries into linear RGB array. */
-  for ( i_row=0; i_row < i_height; i_row ++ ) {
-    for ( i_column=0; i_column<i_width; i_column++ ) {
-      uint8_t *p_rgb = &rgb_palette[ ((*p)&PALETTE_SIZE_MASK)*RGB_SIZE ];
-      *q++ = p_rgb[0];
-      *q++ = p_rgb[1];
-      *q++ = p_rgb[2];
-      p++;
-    }
-  }
-  
-  write_png( filename, i_height, i_width, image_data, text_ptr, i_text_count );
-  free(image_data);
-}
-#endif /*HAVE_LIBPNG*/
-
-\f
-/* 
- * Local variables:
- *  c-file-style: "gnu"
- *  tab-width: 8
- *  indent-tabs-mode: nil
- * End:
- */
diff --git a/modules/codec/ogt/common.h b/modules/codec/ogt/common.h
deleted file mode 100644 (file)
index e11a2f4..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*****************************************************************************
- * Header for Common SVCD and VCD subtitle routines.
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id: common.h,v 1.6 2004/01/16 13:32:37 rocky Exp $
- *
- * Author: Rocky Bernstein
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-void           VCDSubClose  ( vlc_object_t * );
-
-void           VCDSubInitSubtitleBlock( decoder_sys_t * p_sys );
-
-void           VCDSubInitSubtitleData(decoder_sys_t *p_sys);
-
-void           VCDSubAppendData( decoder_t *p_dec, uint8_t *buffer, 
-                                uint32_t buf_len );
-vout_thread_t *VCDSubFindVout( decoder_t *p_dec );
-
-void           VCDSubHandleScaling( subpicture_t *p_spu, decoder_t *p_dec ) ;
-
-
-void           VCDSubScaleX( decoder_t *p_dec, subpicture_t *p_spu, 
-                            unsigned int i_scale_x, unsigned int i_scale_y );
-
-void           VCDSubDestroySPU( subpicture_t *p_spu );
-
-int            VCDSubCropCallback( vlc_object_t *p_object, char const *psz_var,
-                                  vlc_value_t oldval, vlc_value_t newval, 
-                                  void *p_data );
-
-void           VCDSubUpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object );
-
-void           VCDSubDumpImage( uint8_t *p_image, uint32_t i_height, 
-                               uint32_t i_width );
-
-unsigned int   VCDSubGetAROverride(vlc_object_t * p_input, 
-                                  vout_thread_t *p_vout);
-
-#ifdef HAVE_LIBPNG
-#include <png.h>
-void           VCDSubDumpPNG( uint8_t *p_image, decoder_t *p_dec,
-                             uint32_t i_height, uint32_t i_width,
-                             const char *filename,  /*in*/ png_text *text_ptr,
-                             int i_text_count );
-#endif /*HAVE_LIBPNG*/
diff --git a/modules/codec/ogt/cvd.c b/modules/codec/ogt/cvd.c
deleted file mode 100644 (file)
index 87826b5..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/*****************************************************************************
- * cvd.c : CVD Subtitle decoder thread
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id$
- *
- * Authors: Rocky Bernstein
- *   based on code from:
- *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
- *       Samuel Hocevar <sam@zoy.org>
- *       Laurent Aimar <fenrir@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
-
-#include "subtitle.h"
-#include "cvd.h"
-#include "common.h"
-
-/*****************************************************************************
- * Module descriptor.
- *****************************************************************************/
-static int  VCDSubOpen   ( vlc_object_t * );
-static int  PacketizerOpen( vlc_object_t * );
-
-vlc_module_begin();
-    set_description( _("CVD subtitle decoder") );
-    set_capability( "decoder", 50 );
-    set_callbacks( VCDSubOpen, VCDSubClose );
-    set_category( CAT_INPUT );
-    set_subcategory( SUBCAT_INPUT_SCODEC );
-
-    add_integer ( MODULE_STRING "-debug", 0, NULL,
-                  DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
-
-    add_integer ( MODULE_STRING "-horizontal-correct", 0, NULL,
-                  HORIZONTAL_CORRECT, HORIZONTAL_CORRECT_LONGTEXT, VLC_FALSE );
-
-    add_integer ( MODULE_STRING "-vertical-correct", 0, NULL,
-                  VERTICAL_CORRECT, VERTICAL_CORRECT_LONGTEXT, VLC_FALSE );
-
-    add_string( MODULE_STRING "-aspect-ratio", "", NULL,
-                SUB_ASPECT_RATIO_TEXT, SUB_ASPECT_RATIO_LONGTEXT,
-                VLC_TRUE );
-
-    add_integer( MODULE_STRING "-duration-scaling", 3, NULL,
-                 DURATION_SCALE_TEXT, DURATION_SCALE_LONGTEXT,
-                 VLC_TRUE );
-
-    add_submodule();
-    set_description( _("Chaoji VCD subtitle packetizer") );
-    set_capability( "packetizer", 50 );
-    set_callbacks( PacketizerOpen, VCDSubClose );
-vlc_module_end();
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-
-static block_t *Reassemble( decoder_t *, block_t ** );
-static subpicture_t *Decode( decoder_t *, block_t ** );
-static block_t *Packetize( decoder_t *, block_t ** );
-
-/*****************************************************************************
- * VCDSubOpen
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to chose.
- *****************************************************************************/
-static int
-VCDSubOpen( vlc_object_t *p_this )
-{
-    decoder_t     *p_dec = (decoder_t*)p_this;
-    decoder_sys_t *p_sys;
-
-    if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'c','v','d',' ' ) )
-    {
-        return VLC_EGENERIC;
-    }
-
-
-    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
-
-    p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
-    p_sys->b_packetizer  = VLC_FALSE;
-    p_sys->p_vout        = NULL;
-    p_sys->i_image       = -1;
-    p_sys->subtitle_data = NULL;
-
-    VCDSubInitSubtitleBlock( p_sys );
-
-    es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'c','v','d',' ' ) );
-
-
-    p_dec->pf_decode_sub = Decode;
-    p_dec->pf_packetize  = Packetize;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * PacketizerOpen
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to chose.
- *****************************************************************************/
-static int PacketizerOpen( vlc_object_t *p_this )
-{
-    decoder_t *p_dec = (decoder_t*)p_this;
-
-    if( VCDSubOpen( p_this ) )
-    {
-        return VLC_EGENERIC;
-    }
-    p_dec->p_sys->b_packetizer = VLC_TRUE;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Decode:
- *****************************************************************************/
-static subpicture_t *
-Decode ( decoder_t *p_dec, block_t **pp_block )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    block_t       *p_spu = Reassemble( p_dec, pp_block );
-    vout_thread_t *p_last_vout = p_dec->p_sys->p_vout;
-
-    dbg_print( (DECODE_DBG_CALL) , "");
-
-    if( p_spu )
-    {
-        p_sys->i_spu = block_ChainExtract( p_spu, p_sys->buffer, 65536 );
-        p_sys->i_pts = p_spu->i_pts;
-        block_ChainRelease( p_spu );
-
-        if( ( p_sys->p_vout = VCDSubFindVout( p_dec ) ) )
-        {
-            if( p_last_vout != p_sys->p_vout )
-            {
-                spu_Control( p_sys->p_vout->p_spu, SPU_CHANNEL_REGISTER,
-                             &p_sys->i_subpic_channel );
-            }
-
-            /* Parse and decode */
-            E_(ParsePacket)( p_dec );
-
-            vlc_object_release( p_sys->p_vout );
-        }
-
-        VCDSubInitSubtitleBlock ( p_sys );
-    }
-
-    return NULL;
-}
-
-/*****************************************************************************
- * Packetize:
- *****************************************************************************/
-static block_t *
-Packetize( decoder_t *p_dec, block_t **pp_block )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    block_t       *p_spu = Reassemble( p_dec, pp_block );
-
-    if( p_spu )
-    {
-        p_spu->i_dts = p_spu->i_pts;
-        p_spu->i_length = 0;
-
-        VCDSubInitSubtitleBlock( p_sys );
-
-        return block_ChainGather( p_spu );
-    }
-    return NULL;
-}
-
-/* following functions are local */
-
-#define SPU_HEADER_LEN 1
-
-/*****************************************************************************
- Reassemble:
-
- Data for single screen subtitle may come in several non-contiguous
- packets of a stream. This routine is called when the next packet in
- the stream comes in. The job of this routine is to parse the header,
- if this is the beginning, and combine the packets into one complete
- subtitle unit.
-
- If everything is complete, we will return a block. Otherwise return
- NULL.
-
- *****************************************************************************/
-static block_t *
-Reassemble( decoder_t *p_dec, block_t **pp_block )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    block_t *p_block;
-    uint8_t *p_buffer;
-
-    if( pp_block == NULL || *pp_block == NULL )
-    {
-        return NULL;
-    }
-    p_block = *pp_block;
-    *pp_block = NULL;
-
-    if( p_block->i_buffer < SPU_HEADER_LEN )
-    {
-      msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
-               p_block->i_buffer, SPU_HEADER_LEN );
-      block_Release( p_block );
-      return NULL;
-    }
-
-    p_buffer = p_block->p_buffer;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET),
-               "header: 0x%02x 0x%02x 0x%02x 0x%02x, 0x%02x, 0x%02x, size: %i",
-               p_buffer[1], p_buffer[2], p_buffer[3], p_buffer[4],
-               p_buffer[5], p_buffer[6],
-               p_block->i_buffer);
-
-
-    /* Attach to our input thread and see if subtitle is selected. */
-    {
-        vlc_object_t * p_input;
-        vlc_value_t val;
-
-        p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
-
-        if( !p_input ) return NULL;
-
-        if( var_Get( p_input, "spu-channel", &val ) )
-        {
-          vlc_object_release( p_input );
-          return NULL;
-        }
-
-        vlc_object_release( p_input );
-
-        /* Number could be 0bd, 1bd, 2bd, 3bd for 0..3. If so
-           reduce it to 0..3.
-         */
-        if ( (val.i_int & 0xff) == 0xbd ) val.i_int >>= 8;
-
-        if( val.i_int == -1 || val.i_int != p_buffer[0] )
-          return NULL;
-    }
-
-
-    /* From the scant data on the format, there is only only way known
-       to detect the first packet in a subtitle.  The first packet
-       seems to have a valid PTS while later packets for the same
-       image don't. */
-
-    if ( p_sys->state == SUBTITLE_BLOCK_EMPTY && p_block->i_pts == 0 ) {
-      msg_Warn( p_dec,
-                "first packet expected but no PTS present -- skipped\n");
-      return NULL;
-    }
-
-    if ( p_sys->subtitle_data_pos == 0 ) {
-      /* First packet in the subtitle block */
-      E_(ParseHeader)( p_dec, p_buffer, p_block );
-      VCDSubInitSubtitleData(p_sys);
-    }
-
-    /* FIXME - remove append_data and use chainappend */
-    VCDSubAppendData( p_dec, p_buffer + SPU_HEADER_LEN,
-                      p_block->i_buffer - SPU_HEADER_LEN );
-
-    block_ChainAppend( &p_sys->p_block, p_block );
-
-    p_sys->i_spu += p_block->i_buffer - SPU_HEADER_LEN;
-
-    if ( p_sys->subtitle_data_pos == p_sys->i_spu_size ) {
-      E_(ParseMetaInfo)( p_dec );
-      return p_sys->p_block;
-    } else {
-      /* Not last block in subtitle, so wait for another. */
-      p_sys->state = SUBTITLE_BLOCK_PARTIAL;
-    }
-
-    return NULL;
-}
diff --git a/modules/codec/ogt/cvd.h b/modules/codec/ogt/cvd.h
deleted file mode 100644 (file)
index 545134c..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*****************************************************************************
- * cvd.h : CVD subtitles decoder thread interface
- *****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: cvd.h,v 1.2 2004/01/04 04:56:21 rocky Exp $
- *
- * Author: Rocky Bernstein
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-void E_(ParseHeader)( decoder_t *, uint8_t *, block_t *  );
-void E_(ParsePacket)( decoder_t * );
-void E_(ParseMetaInfo)( decoder_t *p_dec  );
diff --git a/modules/codec/ogt/cvd_parse.c b/modules/codec/ogt/cvd_parse.c
deleted file mode 100644 (file)
index 2896197..0000000
+++ /dev/null
@@ -1,547 +0,0 @@
-/*****************************************************************************
- * parse.c: Philips OGT (SVCD subtitle) packet parser
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id$
- *
- * Authors: Rocky Bernstein 
- *   based on code from: 
- *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
- *       Sam Hocevar <sam@zoy.org>
- *       Laurent Aimar <fenrir@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
-
-#include "subtitle.h"
-#include "render.h"
-#include "cvd.h"
-#include "common.h"
-
-#ifdef HAVE_LIBPNG
-#include <png.h>
-#endif
-
-/* An image color is a two-bit palette entry: 0..3 */ 
-typedef uint8_t ogt_color_t;
-
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-static int  ParseImage         ( decoder_t *, subpicture_t * );
-
-/*
-  We do not have information on the subtitle format used on CVD's
-  except the submux sample code and a couple of samples of dubious
-  origin. Thus, this is the result of reading some code whose
-  correctness is not known and some experimentation.
-  
-  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
-  two-bit color number so that up to three pixels can be described in
-  four bits.  The function of a 0 repeat count is unknown; it might be
-  used for RLE extension.  However 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.
-*/
-
-void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
-{
-  decoder_sys_t *p_sys = p_dec->p_sys;
-  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",
-            p_buffer[0], p_buffer[1], p_buffer[2], p_buffer[3],
-            p_buffer[4], p_buffer[5],
-            p_block->i_buffer);
-  
-  dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
-
-  p_sys->i_pts    = p_block->i_pts;
-  p_sys->i_spu_size = (p[0] << 8) + p[1] + 4; p += 2;
-
-  /* FIXME: check data sanity */
-  p_sys->metadata_offset = GETINT16(p);
-  p_sys->metadata_length = p_sys->i_spu_size - p_sys->metadata_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->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. */
-  
-  decoder_sys_t *p_sys = p_dec->p_sys;
-  uint8_t       *p     = p_sys->subtitle_data + p_sys->metadata_offset;
-  uint8_t       *p_end = p + p_sys->metadata_length;
-  
-  dbg_print( (DECODE_DBG_PACKET),
-            "subtitle packet complete, size=%d", p_sys->i_spu );
-  
-  p_sys->state = SUBTITLE_BLOCK_COMPLETE;
-  p_sys->i_image++;
-  
-  for ( ; p < p_end; p += 4 ) {
-    
-    switch ( p[0] ) {
-      
-    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;
-      }
-      
-      
-    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: /* coordinates of subtitle upper left x, y position */
-      ExtractXY(p_sys->i_x_start, p_sys->i_y_start);
-      break;
-      
-    case 0x1f: /* coordinates of subtitle bottom right x, y position */
-      {
-       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, 
-                  "end position: (%d,%d): %.2x %.2x %.2x, w x h: %dx%d",
-                  lastx, lasty, p[1], p[2], p[3], 
-                  p_sys->i_width, p_sys->i_height );
-       break;
-      }
-      
-      
-    case 0x24:
-    case 0x25:
-    case 0x26:
-    case 0x27: 
-      {
-       uint8_t v = p[0]-0x24;
-       
-       /* Primary Palette */
-       dbg_print( DECODE_DBG_PACKET,
-                  "primary palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
-                  v, p[1], p[2], p[3]);
-       
-       p_sys->p_palette[v].s.y = p[1];
-       p_sys->p_palette[v].s.u = p[2];
-       p_sys->p_palette[v].s.v = p[3];
-       break;
-      }
-      
-      
-    case 0x2c:
-    case 0x2d:
-    case 0x2e:
-    case 0x2f:
-      {
-       uint8_t v = p[0]-0x2c;
-       
-       dbg_print( DECODE_DBG_PACKET,
-                  "highlight palette %d (y,u,v): (0x%0x,0x%0x,0x%0x)",
-                  v, p[1], p[2], p[3]);
-       
-       /* Highlight Palette */
-       p_sys->p_palette_highlight[v].s.y = p[1];
-       p_sys->p_palette_highlight[v].s.u = p[2];
-       p_sys->p_palette_highlight[v].s.v = p[3];
-       break;
-      }
-      
-    case 0x37:
-      /* transparency for primary palette */
-      p_sys->p_palette[0].s.t = p[3] & 0x0f;
-      p_sys->p_palette[1].s.t = p[3] >> 4;
-      p_sys->p_palette[2].s.t = p[2] & 0x0f;
-      p_sys->p_palette[3].s.t = p[2] >> 4;
-      
-      dbg_print( DECODE_DBG_PACKET,
-                "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,
-                p_sys->p_palette[2].s.t,
-                p_sys->p_palette[3].s.t );
-      
-      break;
-      
-    case 0x3f:
-      /* transparency for highlight palette */
-      p_sys->p_palette_highlight[0].s.t = p[2] & 0x0f;
-      p_sys->p_palette_highlight[1].s.t = p[2] >> 4;
-      p_sys->p_palette_highlight[2].s.t = p[1] & 0x0f;
-      p_sys->p_palette_highlight[3].s.t = p[1] >> 4;
-      
-      dbg_print( DECODE_DBG_PACKET,
-                "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,
-                p_sys->p_palette_highlight[2].s.t,
-                p_sys->p_palette_highlight[3].s.t );
-      
-      break;
-      
-    case 0x47:
-      /* 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->i_image_offset;
-      dbg_print( DECODE_DBG_PACKET, 
-                "first_field_offset %d", p_sys->first_field_offset);
-      break;
-      
-    case 0x4f:
-      /* 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->i_image_offset;
-      dbg_print( DECODE_DBG_PACKET, 
-                "second_field_offset %d", p_sys->second_field_offset);
-      break;
-      
-    default:
-      msg_Warn( p_dec, 
-               "unknown sequence in control header " 
-               "0x%0x 0x%0x 0x%0x 0x%0x",
-               p[0], p[1], p[2], p[3]);
-      
-      p_sys->subtitle_data_pos = 0;
-    }
-  }
-}
-
-/*****************************************************************************
- * ParsePacket: parse an SPU packet and send it to the video output
- *****************************************************************************
- * This function parses the SPU packet and, if valid, sends it to the
- * video output.
- *****************************************************************************/
-void 
-E_(ParsePacket)( decoder_t *p_dec)
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    subpicture_t  *p_spu;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
-
-    /* Allocate the subpicture internal data. */
-    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
-       facilitate scaling and antialiasing and speed up rendering.
-    */
-    p_spu->p_sys = malloc( sizeof( subpicture_sys_t ) 
-                          + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
-
-    /* Fill the p_spu structure */
-    vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
-
-    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_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);
-    
-    p_spu->p_sys->b_crop  = VLC_FALSE;
-    p_spu->p_sys->i_debug = p_sys->i_debug;
-
-    /* Get display time now. If we do it later, we may miss the PTS. */
-    p_spu->p_sys->i_pts = p_sys->i_pts;
-
-    /* Attach to our input thread */
-    p_spu->p_sys->p_input = vlc_object_find( p_dec,
-                                             VLC_OBJECT_INPUT, FIND_PARENT );
-
-    /* We try to display it */
-    if( ParseImage( p_dec, p_spu ) )
-    {
-        /* There was a parse error, delete the subpicture */
-        spu_DestroySubpicture( p_sys->p_vout->p_spu, p_spu );
-        return;
-    }
-
-    /* SPU is finished - we can ask the video output to display it */
-    spu_DisplaySubpicture( p_sys->p_vout->p_spu, p_spu );
-
-}
-
-#define advance_color_byte_pointer                                     \
-  p++;                                                                 \
-  i_nibble_field = 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 "              \
-             " padding (%d,%d,%d)\n",                                  \
-             i_field, i_row, i_column );                               \
-    return VLC_EGENERIC;                                               \
-  }                                                                    
-
-#define CVD_FIELD_BITS (4)
-#define CVD_FIELD_MASK  ((1<<CVD_FIELD_BITS) - 1) 
-
-/* Get the next field - a 2-bit palette index and a run count.  To do
-   this we use byte image pointer p, and i_nibble_field which
-   indicates where we are in the byte.
-*/
-static inline uint8_t
-ExtractField(uint8_t *p, uint8_t i_nibble_field) 
-{
-  return ( ( *p >> (CVD_FIELD_BITS*(i_nibble_field-1)) ) & CVD_FIELD_MASK );
-}
-
-/*****************************************************************************
- * ParseImage: parse the image part of the subtitle
- *****************************************************************************
- This part parses the subtitle graphical data and stores it in a more
- convenient structure for later rendering. 
-
- 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 
- a 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
-
- *****************************************************************************/
-static int 
-ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    uint8_t 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_nibble_field;    /* The 2-bit pixels remaining in byte of *p.
-                                 Has value 0..2. */
-    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->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);
-
-    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_nibble_field = 2;  /* 4-bit pieces available in *p */
-
-#if 0
-      unsigned int i;
-      int8_t *b=p;
-      for (i=0; i< i_width * i_height; i++)
-       printf ("%02x", b[i]);
-      printf("\n");
-#endif
-    
-      for ( i_row=i_field; i_row < i_height; i_row += 2 ) {
-       b_filling   = VLC_FALSE;
-       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_nibble_field--);
-           if ( i_nibble_field == 0 ) {
-             advance_color_byte_pointer;
-           }
-           if ( i_val == 0 ) {
-             /* fill the rest of the line with next color */
-             i_color = ExtractField( p, i_nibble_field-- );
-             if ( i_nibble_field == 0 ) {
-               p++;
-               i_nibble_field=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_nibble_field == 1 ) {
-         advance_color_byte_pointer;
-       }
-
-       if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE) 
-         printf("\n");
-      }
-    }
-
-    if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE)) {
-      /* Dump out image not interlaced... */
-      VCDSubDumpImage( p_dest, i_height, i_width );
-    }
-
-#ifdef HAVE_LIBPNG
-    if (p_sys && (p_sys->i_debug & DECODE_DBG_PNG)) {
-#define TEXT_COUNT 2
-      /* Dump image to a file in PNG format. */
-      char filename[300];
-      png_text text_ptr[TEXT_COUNT];
-
-      text_ptr[0].key = "Preparer";
-      text_ptr[0].text = "VLC";
-      text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
-      text_ptr[1].key = "Description";
-      text_ptr[1].text = "CVD Subtitle";
-      text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
-
-      snprintf(filename, 300, "%s%d.png", "/tmp/vlc-cvd-sub", p_sys->i_image);
-      VCDSubDumpPNG( p_dest, p_dec, i_height, i_width, filename,
-                    text_ptr, TEXT_COUNT );
-    }
-#endif /*HAVE_LIBPNG*/
-
-    VCDSubHandleScaling( p_spu, p_dec );
-
-    return VLC_SUCCESS;
-
-}
-
diff --git a/modules/codec/ogt/ogt.c b/modules/codec/ogt/ogt.c
deleted file mode 100644 (file)
index 54eca68..0000000
+++ /dev/null
@@ -1,348 +0,0 @@
-/*****************************************************************************
- * ogt.c : Overlay Graphics Text (SVCD subtitles) decoder thread
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id$
- *
- * Author: Rocky Bernstein
- *   based on code from:
- *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
- *       Samuel Hocevar <sam@zoy.org>
- *       Laurent Aimar <fenrir@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
-
-#include "subtitle.h"
-#include "ogt.h"
-#include "common.h"
-
-/*****************************************************************************
- * Module descriptor.
- *****************************************************************************/
-static int  VCDSubOpen   ( vlc_object_t * );
-static int  PacketizerOpen( vlc_object_t * );
-
-vlc_module_begin();
-    set_description( _("Philips OGT (SVCD subtitle) decoder") );
-    set_capability( "decoder", 50 );
-    set_callbacks( VCDSubOpen, VCDSubClose );
-
-    add_integer ( MODULE_STRING "-debug", 0, NULL,
-                  DEBUG_TEXT, DEBUG_LONGTEXT, VLC_TRUE );
-
-    add_integer ( MODULE_STRING "-horizontal-correct", 0, NULL,
-                  HORIZONTAL_CORRECT, HORIZONTAL_CORRECT_LONGTEXT, VLC_FALSE );
-
-    add_integer ( MODULE_STRING "-vertical-correct", 0, NULL,
-                  VERTICAL_CORRECT, VERTICAL_CORRECT_LONGTEXT, VLC_FALSE );
-
-    add_string( MODULE_STRING "-aspect-ratio", "", NULL,
-                SUB_ASPECT_RATIO_TEXT, SUB_ASPECT_RATIO_LONGTEXT, VLC_TRUE );
-
-    add_integer( MODULE_STRING "-duration-scaling", 9, NULL,
-                 DURATION_SCALE_TEXT, DURATION_SCALE_LONGTEXT, VLC_TRUE );
-
-    add_submodule();
-    set_description( _("Philips OGT (SVCD subtitle) packetizer") );
-    set_capability( "packetizer", 50 );
-    set_callbacks( PacketizerOpen, VCDSubClose );
-vlc_module_end();
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-
-static block_t *Reassemble ( decoder_t *, block_t ** );
-static subpicture_t *Decode( decoder_t *, block_t ** );
-static block_t *Packetize  ( decoder_t *, block_t ** );
-
-/*****************************************************************************
- * VCDSubOpen
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to chose.
- *****************************************************************************/
-static int
-VCDSubOpen( vlc_object_t *p_this )
-{
-    decoder_t     *p_dec = (decoder_t*)p_this;
-    decoder_sys_t *p_sys;
-
-    if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
-    {
-        return VLC_EGENERIC;
-    }
-
-
-    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
-
-    p_sys->i_debug       = config_GetInt( p_this, MODULE_STRING "-debug" );
-    p_sys->b_packetizer  = VLC_FALSE;
-    p_sys->p_vout        = NULL;
-    p_sys->i_image       = -1;
-    p_sys->subtitle_data = NULL;
-
-    VCDSubInitSubtitleBlock( p_sys );
-
-    es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
-
-
-    p_dec->pf_decode_sub = Decode;
-    p_dec->pf_packetize  = Packetize;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * PacketizerOpen
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to chose.
- *****************************************************************************/
-static int PacketizerOpen( vlc_object_t *p_this )
-{
-    decoder_t *p_dec = (decoder_t*)p_this;
-
-    if( VCDSubOpen( p_this ) )
-    {
-        return VLC_EGENERIC;
-    }
-    p_dec->p_sys->b_packetizer = VLC_TRUE;
-
-    return VLC_SUCCESS;
-}
-
-/*****************************************************************************
- * Decode:
- *****************************************************************************/
-static subpicture_t *
-Decode ( decoder_t *p_dec, block_t **pp_block )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    block_t       *p_spu = Reassemble( p_dec, pp_block );
-    vout_thread_t *p_last_vout = p_dec->p_sys->p_vout;
-
-    dbg_print( (DECODE_DBG_CALL) , "");
-
-    if( p_spu )
-    {
-        p_sys->i_spu = block_ChainExtract( p_spu, p_sys->buffer, 65536 );
-        p_sys->i_pts = p_spu->i_pts;
-        block_ChainRelease( p_spu );
-
-        if( ( p_sys->p_vout = VCDSubFindVout( p_dec ) ) )
-        {
-            if( p_last_vout != p_sys->p_vout )
-            {
-                spu_Control( p_sys->p_vout->p_spu, SPU_CHANNEL_REGISTER,
-                             &p_sys->i_subpic_channel );
-            }
-
-            /* Parse and decode */
-            E_(ParsePacket)( p_dec );
-
-            vlc_object_release( p_sys->p_vout );
-        }
-
-        VCDSubInitSubtitleBlock ( p_sys );
-    }
-
-    return NULL;
-}
-
-/*****************************************************************************
- * Packetize:
- *****************************************************************************/
-static block_t *
-Packetize( decoder_t *p_dec, block_t **pp_block )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    block_t       *p_spu = Reassemble( p_dec, pp_block );
-
-    if( p_spu )
-    {
-        p_spu->i_dts = p_spu->i_pts;
-        p_spu->i_length = 0;
-
-        VCDSubInitSubtitleBlock( p_sys );
-
-        return block_ChainGather( p_spu );
-    }
-    return NULL;
-}
-
-#define SPU_HEADER_LEN 5
-
-/*****************************************************************************
- Reassemble:
-
- The data for single screen subtitle may come in one of many
- non-contiguous packets of a stream. This routine is called when the
- next packet in the stream comes in. The job of this routine is to
- parse the header, if this is the beginning, and combine the packets
- into one complete subtitle unit.
-
- If everything is complete, we will return a block. Otherwise return
- NULL.
-
-
- The format of the beginning of the subtitle packet that is used here.
-
-   size    description
-   -------------------------------------------
-   byte    subtitle channel (0..7) in bits 0-3
-   byte    subtitle packet number of this subtitle image 0-N,
-           if the subtitle packet is complete, the top bit of the byte is 1.
-   uint16  subtitle image number
-
- *****************************************************************************/
-static block_t *
-Reassemble( decoder_t *p_dec, block_t **pp_block )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-    block_t *p_block;
-    uint8_t *p_buffer;
-    uint16_t i_expected_image;
-    uint8_t  i_packet, i_expected_packet;
-
-    if( pp_block == NULL || *pp_block == NULL )
-    {
-        return NULL;
-    }
-    p_block = *pp_block;
-    *pp_block = NULL;
-
-    if( p_block->i_buffer < SPU_HEADER_LEN )
-    {
-      msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
-               p_block->i_buffer, SPU_HEADER_LEN );
-      block_Release( p_block );
-      return NULL;
-    }
-
-    p_buffer = p_block->p_buffer;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET),
-               "header: 0x%02x 0x%02x 0x%02x 0x%02x, size: %i",
-               p_buffer[1], p_buffer[2], p_buffer[3], p_buffer[4],
-               p_block->i_buffer);
-
-    /* Attach to our input thread and see if subtitle is selected. */
-    {
-        vlc_object_t * p_input;
-        vlc_value_t val;
-
-        p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
-
-        if( !p_input ) return NULL;
-
-        if( var_Get( p_input, "spu-channel", &val ) )
-        {
-            vlc_object_release( p_input );
-          return NULL;
-        }
-
-        vlc_object_release( p_input );
-        dbg_print( (DECODE_DBG_PACKET),
-                   "val.i_int %x p_buffer[i] %x", val.i_int, p_buffer[1]);
-
-        /* The dummy ES that the menu selection uses has an 0x70 at
-           the head which we need to strip off. */
-        if( val.i_int == -1 || (val.i_int & 0x03) != p_buffer[1] )
-        {
-            dbg_print( DECODE_DBG_PACKET, "subtitle not for us.\n");
-            return NULL;
-        }
-    }
-
-    if ( p_sys->state == SUBTITLE_BLOCK_EMPTY ) {
-      i_expected_image  = p_sys->i_image+1;
-      i_expected_packet = 0;
-    } else {
-      i_expected_image  = p_sys->i_image;
-      i_expected_packet = p_sys->i_packet+1;
-    }
-
-    p_buffer += 2;
-
-    if ( *p_buffer & 0x80 ) {
-      p_sys->state = SUBTITLE_BLOCK_COMPLETE;
-      i_packet     = ( *p_buffer++ & 0x7F );
-    } else {
-      p_sys->state = SUBTITLE_BLOCK_PARTIAL;
-      i_packet     = *p_buffer++;
-    }
-
-    p_sys->i_image = GETINT16(p_buffer);
-
-    if ( p_sys->i_image != i_expected_image ) {
-      msg_Warn( p_dec, "expecting subtitle image %u but found %u",
-                i_expected_image, p_sys->i_image );
-    }
-
-    if ( i_packet != i_expected_packet ) {
-      msg_Warn( p_dec, "expecting subtitle image packet %u but found %u",
-                i_expected_packet, i_packet);
-    }
-
-    p_sys->i_packet = i_packet;
-
-    if ( p_sys->i_packet == 0 ) {
-      /* First packet in the subtitle block */
-      E_(ParseHeader)( p_dec, p_buffer, p_block );
-      VCDSubInitSubtitleData(p_sys);
-    }
-
-    /* FIXME - remove append_data and use chainappend */
-    VCDSubAppendData( p_dec, p_buffer, p_block->i_buffer - SPU_HEADER_LEN );
-
-    block_ChainAppend( &p_sys->p_block, p_block );
-
-    p_sys->i_spu += p_block->i_buffer - SPU_HEADER_LEN;
-
-    if (p_sys->state == SUBTITLE_BLOCK_COMPLETE)
-    {
-      if( p_sys->i_spu != p_sys->i_spu_size )
-        {
-          msg_Warn( p_dec, "SPU packets size=%d should be %d",
-                   p_sys->i_spu, p_sys->i_spu_size );
-        }
-
-      dbg_print( (DECODE_DBG_PACKET),
-                 "subtitle packet complete, size=%d", p_sys->i_spu );
-
-      return p_sys->p_block;
-    }
-    return NULL;
-}
-
-\f
-/*
- * Local variables:
- *  c-file-style: "gnu"
- *  tab-width: 8
- *  indent-tabs-mode: nil
- * End:
- */
diff --git a/modules/codec/ogt/ogt.h b/modules/codec/ogt/ogt.h
deleted file mode 100644 (file)
index 1e8e0da..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*****************************************************************************
- * ogt.h : Overlay Graphics Text (SVCD subtitles) decoder thread interface
- *****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: ogt.h,v 1.6 2003/12/28 02:01:11 rocky Exp $
- *
- * Author: Rocky Bernstein
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-void E_(ParseHeader)( decoder_t *, uint8_t *, block_t *  );
-void E_(ParsePacket)( decoder_t * );
-
diff --git a/modules/codec/ogt/ogt_parse.c b/modules/codec/ogt/ogt_parse.c
deleted file mode 100644 (file)
index a386ba3..0000000
+++ /dev/null
@@ -1,390 +0,0 @@
-/*****************************************************************************
- * Philips OGT (SVCD subtitle) packet parser
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id$
- *
- * Author: Rocky Bernstein 
- *   based on code from: 
- *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
- *       Sam Hocevar <sam@zoy.org>
- *       Laurent Aimar <fenrir@via.ecp.fr>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
-
-#include "subtitle.h"
-#include "common.h"
-#include "render.h"
-#include "ogt.h"
-
-#ifdef HAVE_LIBPNG
-#include <png.h>
-#endif
-
-/* An image color is a two-bit palette entry: 0..3 */ 
-typedef uint8_t ogt_color_t;
-
-/*****************************************************************************
- * Local prototypes.
- *****************************************************************************/
-static int  ParseImage         ( decoder_t *, subpicture_t * );
-
-/*
-  The format is roughly as follows (everything is big-endian):
-   size     description
-   -------------------------------------------
-   byte     subtitle channel (0..7) in bits 0-3 
-   byte     subtitle packet number of this subtitle image 0-N,
-            if the subtitle packet is complete, the top bit of the byte is 1.
-   u_int16  subtitle image number
-   u_int16  length in bytes of the rest
-   byte     option flags, unknown meaning except bit 3 (0x08) indicates
-           presence of the duration field
-   byte     unknown 
-   u_int32  duration in 1/90000ths of a second (optional), start time
-           is as indicated by the PTS in the PES header
-   u_int32  xpos
-   u_int32  ypos
-   u_int32  width (must be even)
-   u_int32  height (must be even)
-   byte[16] palette, 4 palette entries, each contains values for
-           Y, U, V and transparency, 0 standing for transparent
-   byte     command,
-           cmd>>6==1 indicates shift
-           (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
-   u_int32  shift duration in 1/90000ths of a second
-   u_int16  offset of odd-numbered scanlines - subtitle images are 
-            given in interlace order
-   byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
-            2-bits per palette number
-*/
-
-/* FIXME: do we really need p_buffer and p? 
-   Can't all of thes _offset's and _lengths's get removed? 
-*/
-void E_(ParseHeader)( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
-{
-  decoder_sys_t *p_sys = p_dec->p_sys;
-  uint8_t *p = p_buffer;
-  int i;
-
-  dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
-
-  p_sys->i_pts    = p_block->i_pts;
-  p_sys->i_spu_size = GETINT16(p);
-  p_sys->i_options  = *p++;
-  p_sys->i_options2 = *p++;
-  
-  if ( p_sys->i_options & 0x08 ) {
-    p_sys->i_duration = GETINT32(p);
-    p_sys->i_duration *= config_GetInt( p_dec, MODULE_STRING 
-                                        "-duration-scaling" );
-  } else {
-    /* 0 means display until next subtitle comes in. */
-    p_sys->i_duration = 0;
-  }
-  p_sys->i_x_start= GETINT16(p);
-  p_sys->i_y_start= GETINT16(p);
-  p_sys->i_width  = GETINT16(p);
-  p_sys->i_height = GETINT16(p);
-  
-  for (i=0; i<4; i++) {
-    p_sys->p_palette[i].s.y = *p++;
-    p_sys->p_palette[i].s.u = *p++;
-    p_sys->p_palette[i].s.v = *p++;
-    /* 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->p_palette[i].s.t = (*p++) >> 4;
-  }
-  p_sys->i_cmd = *p++;
-      /* We do not really know this, FIXME */
-  if ( p_sys->i_cmd ) {
-    p_sys->i_cmd_arg = GETINT32(p);
-  }
-
-  /* Actually, this is measured against a different origin, so we have to
-     adjust it */
-  p_sys->second_field_offset = GETINT16(p);
-  p_sys->i_image_offset  = p - p_buffer;
-  p_sys->i_image_length  = p_sys->i_spu_size - p_sys->i_image_offset;
-  p_sys->metadata_length = p_sys->i_image_offset;
-
-  if (p_sys && p_sys->i_debug & DECODE_DBG_PACKET) {
-    msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
-            "spu size: %d, duration: %lu (d:%d p:%d)",
-            p_sys->i_x_start, p_sys->i_y_start, 
-            p_sys->i_width, p_sys->i_height, 
-            p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
-            p_sys->i_image_length, p_sys->i_image_offset);
-    
-    for (i=0; i<4; i++) {
-      msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
-              p_sys->p_palette[i].s.t, p_sys->p_palette[i].s.y, 
-              p_sys->p_palette[i].s.u, p_sys->p_palette[i].s.v );
-    }
-  }
-}
-
-
-/*****************************************************************************
- * ParsePacket: parse an SPU packet and send it to the video output
- *****************************************************************************
- * This function parses the SPU packet and, if valid, sends it to the
- * video output.
- *****************************************************************************/
-void 
-E_(ParsePacket)( decoder_t *p_dec)
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    subpicture_t  *p_spu;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_EXT) , "");
-    
-    /* Allocate the subpicture internal data. */
-    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
-       facilitate scaling and antialiasing and speed up rendering.
-    */
-    p_spu->p_sys = malloc( sizeof( subpicture_sys_t ) 
-                          + PIXEL_SIZE * (p_sys->i_width * p_sys->i_height) );
-
-    /* Fill the p_spu structure */
-    vlc_mutex_init( p_dec, &p_spu->p_sys->lock );
-
-    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_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;
-    
-    p_spu->p_sys->b_crop  = VLC_FALSE;
-    p_spu->p_sys->i_debug = p_sys->i_debug;
-
-    /* Get display time now. If we do it later, we may miss the PTS. */
-    p_spu->p_sys->i_pts = p_sys->i_pts;
-
-    /* Attach to our input thread */
-    p_spu->p_sys->p_input = vlc_object_find( p_dec,
-                                             VLC_OBJECT_INPUT, FIND_PARENT );
-
-    /* We try to display it */
-    if( ParseImage( p_dec, p_spu ) )
-    {
-        /* There was a parse error, delete the subpicture */
-        spu_DestroySubpicture( p_sys->p_vout->p_spu, p_spu );
-        return;
-    }
-
-    /* SPU is finished - we can ask the video output to display it */
-    spu_DisplaySubpicture( p_sys->p_vout->p_spu, p_spu );
-
-}
-
-/* Advance pointer to image pointer, update internal i_2bit_field counter
-   and check that we haven't goine too far  in the image data. */
-#define advance_color_pointer_byte                                     \
-  p++;                                                                 \
-  i_2bit_field=4;                                                      \
-  if (p >= maxp) {                                                     \
-    msg_Warn( p_dec,                                                   \
-             "broken subtitle - tried to access beyond end "           \
-             "in image extraction");                                   \
-    return VLC_EGENERIC;                                               \
-  }                                                                    \
-
-#define advance_color_pointer                                          \
-  i_2bit_field--;                                                      \
-  if ( i_2bit_field == 0 ) {                                           \
-    advance_color_pointer_byte;                                                \
-  }                                                                    
-
-#define OGT_FIELD_BITS (2)
-#define OGT_FIELD_MASK  ((1<<OGT_FIELD_BITS) - 1) 
-
-/* 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_2bit_field
-   which indicates where we are in the byte.
-*/
-static inline ogt_color_t 
-ExtractField(uint8_t *p, unsigned int i_2bit_field) 
-{
-  return ( ( *p >> (OGT_FIELD_BITS*(i_2bit_field-1)) ) & OGT_FIELD_MASK );
-}
-
-/*****************************************************************************
- * ParseImage: parse the image part of the subtitle
- *****************************************************************************
- 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.
-
- 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 4-bit alpha (filling 8 bits), and 8-bit y, u, and v entry.
-
- *****************************************************************************/
-static int 
-ParseImage( decoder_t *p_dec, subpicture_t * p_spu )
-{
-    decoder_sys_t *p_sys = p_dec->p_sys;
-
-    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_2bit_field;           /* The 2-bit field to sue in byte of *p.
-                                      Has value 0..4. */
-    uint8_t i_pending_zero = 0;    /* number of pixels to fill with 
-                                     color zero 0..3 */
-    ogt_color_t i_color;           /* current pixel color: 0..3 */
-    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);
-
-    if (p_sys && p_sys->i_debug & DECODE_DBG_IMAGE)    
-      printf("\n");
-
-    for ( i_field=0; i_field < 2; i_field++ ) {
-      i_2bit_field = 4;
-      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_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 {
-           i_color = ExtractField( p, i_2bit_field );
-           advance_color_pointer;
-           if ( i_color == 0 ) {
-             i_pending_zero = ExtractField( p, i_2bit_field );
-             advance_color_pointer;
-             /* Fall through with i_color == 0 to output the first cell */
-           }
-         }
-
-         /* 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 (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE))
-         printf("\n");
-
-       if ( i_2bit_field != 4 ) {
-         /* Lines are padded to complete bytes, ignore padding */
-         advance_color_pointer_byte;
-       }
-      }
-      p = p_sys->subtitle_data + p_sys->i_image_offset 
-       + p_sys->second_field_offset;
-    }
-
-    if (p_sys && (p_sys->i_debug & DECODE_DBG_IMAGE)) {
-      /* Dump out image not interlaced... */
-      VCDSubDumpImage( p_dest, i_height, i_width );
-    }
-
-#ifdef HAVE_LIBPNG
-    if (p_sys && (p_sys->i_debug & DECODE_DBG_PNG)) {
-#define TEXT_COUNT 2
-      /* Dump image to a file in PNG format. */
-      char filename[300];
-      png_text text_ptr[TEXT_COUNT];
-
-      text_ptr[0].key = "Preparer";
-      text_ptr[0].text = "VLC";
-      text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
-      text_ptr[1].key = "Description";
-      text_ptr[1].text = "SVCD Subtitle";
-      text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
-
-      snprintf(filename, 300, "%s%d.png", "/tmp/vlc-svcd-sub", p_sys->i_image);
-      VCDSubDumpPNG( p_dest, p_dec, i_height, i_width, filename,
-                    text_ptr, TEXT_COUNT );
-    }
-#endif /*HAVE_LIBPNG*/
-    
-    VCDSubHandleScaling( p_spu, p_dec );
-    return VLC_SUCCESS;
-}
-
-\f
-/* 
- * Local variables:
- *  c-file-style: "gnu"
- *  tab-width: 8
- *  indent-tabs-mode: nil
- * End:
- */
diff --git a/modules/codec/ogt/pixmap.c b/modules/codec/ogt/pixmap.c
deleted file mode 100644 (file)
index 42e4536..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/*****************************************************************************
- * Common pixel/chroma manipulation routines.
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id: pixmap.c,v 1.3 2004/01/31 05:53:35 rocky Exp $
- *
- * Author: Rocky Bernstein
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-
-#include "pixmap.h"
-
-/* FIXME: This is copied from modules/video_chroma/i420_rgb.h. 
-   Include from a more common location.
- */
-
-/*****************************************************************************
- * chroma_sys_t: chroma method descriptor
- *****************************************************************************
- * This structure is part of the chroma transformation descriptor, it
- * describes the yuv2rgb specific properties.
- *****************************************************************************/
-struct chroma_sys_t
-{
-    uint8_t  *p_buffer;
-    int *p_offset;
-
-    /* Pre-calculated conversion tables */
-    void *p_base;                         /* base for all conversion tables */
-    uint8_t   *p_rgb8;                    /* RGB 8 bits table */
-    uint16_t  *p_rgb16;                   /* RGB 16 bits table */
-    uint32_t  *p_rgb32;                   /* RGB 32 bits table */
-
-    /* To get RGB value for palette entry i, use (p_rgb_r[i], p_rgb_g[i],
-       p_rgb_b[i])
-     */
-    uint16_t  p_rgb_r[CMAP_RGB2_SIZE];    /* Red values of palette */
-    uint16_t  p_rgb_g[CMAP_RGB2_SIZE];    /* Green values of palette */
-    uint16_t  p_rgb_b[CMAP_RGB2_SIZE];    /* Blue values of palette */
-};
-
-
-/* 
-    From
-    http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC11
-    http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html#RTFToC1
-    11. What is "luma"?
-
-    It is useful in a video system to convey a component representative of
-    luminance and two other components representative of colour. It is
-    important to convey the component representative of luminance in such
-    a way that noise (or quantization) introduced in transmission,
-    processing and storage has a perceptually similar effect across the
-    entire tone scale from black to white. The ideal way to accomplish
-    these goals would be to form a luminance signal by matrixing RGB, then
-    subjecting luminance to a nonlinear transfer function similar to the
-    L* function.
-
-    There are practical reasons in video to perform these operations
-    in the opposite order. First a nonlinear transfer function - gamma
-    correction - is applied to each of the linear R, G and B. Then a
-    weighted sum of the nonlinear components is computed to form a
-    signal representative of luminance. The resulting component is
-    related to brightness but is not CIE luminance. Many video
-    engineers call it luma and give it the symbol Y'. It is often
-    carelessly called luminance and given the symbol Y. You must be
-    careful to determine whether a particular author assigns a linear
-    or nonlinear interpretation to the term luminance and the symbol
-    Y.
-
-    The coefficients that correspond to the "NTSC" red, green and blue
-    CRT phosphors of 1953 are standardized in ITU-R Recommendation BT.
-    601-2 (formerly CCIR Rec.  601-2). I call it Rec.  601. To compute
-    nonlinear video luma from nonlinear red, green and blue:
-
-    Y'601 = 0.299R' 0.587G' + 0.114B'
-
-    We will use the integer scaled versions of these numbers below
-    as RED_COEF, GREEN_COEF and BLUE_COEF.
- */
-
-/* 19 = round(0.299 * 64) */
-#define RED_COEF   ((int32_t) 19)
-
-/* 38 = round(0.587 * 64) */
-#define GREEN_COEF ((int32_t) 37)
-
-/* 7 = round(0.114 * 64) */
-#define BLUE_COEF  ((int32_t)  7)
-
-/** 
-   Find the nearest colormap entry in p_vout (assumed to have RGB2
-   chroma, i.e. 256 RGB 8bpp entries) that is closest in color to p_rgb.  Set
-   out_rgb to the color found and return the colormap index.
-   INVALID_CMAP_ENTRY is returned if there is some error.
-
-   The closest match is determined by the the Euclidean distance
-   using integer-scaled 601-2 coefficients described above.
-
-   Actually, we use the square of the Euclidean distance; but in
-   comparisons it amounts to the same thing.
-*/
-
-cmap_t
-find_cmap_rgb8_nearest(const vout_thread_t *p_vout, const uint8_t *rgb,
-                      uint8_t *out_rgb) 
-{
-  uint16_t *p_cmap_r;
-  uint16_t *p_cmap_g;
-  uint16_t *p_cmap_b;
-  
-  int i;
-  cmap_t i_bestmatch = INVALID_CMAP_ENTRY;
-  uint32_t i_mindist = 0xFFFFFFFF; /* The largest number here. */
-
-  /* Check that we really have RGB2. */
-  
-  if ( !p_vout && p_vout->output.i_chroma  != VLC_FOURCC('R','G','B','2') )
-    return INVALID_CMAP_ENTRY;
-
-  p_cmap_r=p_vout->chroma.p_sys->p_rgb_r;
-  p_cmap_g=p_vout->chroma.p_sys->p_rgb_g;
-  p_cmap_b=p_vout->chroma.p_sys->p_rgb_b;
-
-  for (i = 0; i < CMAP_RGB2_SIZE; i++) {
-    /* Interval range calculations to show that we don't overflow the
-       word sizes below. pixels component values start out 8
-       bits. When we subtract two components we get 9 bits, then
-       square to 10 bits.  Next we scale by 6 to give 16
-       bits. XXX_COEF all fit into 5 bits, so when we multiply we
-       should have 21 bits maximum. So computations can be done using
-       32-bit precision. However before storing back distance
-       components we scale back down by 12 bits making the precision 9
-       bits. (This checks out since it is basically the range of the
-       square of the initial 8-bit value.)
-
-       The squared distance is the sum of three of the 9-bit components
-       described above. This then uses 27-bits and also fits in a
-       32-bit word.
-     */
-
-    /* We use in integer fixed-point fractions rather than floating
-       point for speed. We multiply by 64 (= 1 << 6) before computing
-       the product, and divide the result by 64*64 (= 1 >> (6*2)).
-    */
-
-#define SCALEBITS 6 
-#define int32_sqr(x) ( ((int32_t) (x)) * ((int32_t) x) )
-
-    /* colormap entires are scaled to 16 bits, so we need to shift
-       them back down to 8. */
-#define CMAP8_RED(i) (p_cmap_r[i]>>8)
-#define CMAP8_GREEN(i) (p_cmap_g[i]>>8)
-#define CMAP8_BLUE(i) (p_cmap_b[i]>>8)
-
-    uint32_t dr = ( RED_COEF   * ( int32_sqr(rgb[RED_PIXEL]   - CMAP8_RED(i))
-                                << SCALEBITS ) ) >> (SCALEBITS*2);
-    uint32_t dg = ( GREEN_COEF * ( int32_sqr(rgb[GREEN_PIXEL] - CMAP8_GREEN(i))
-                                << SCALEBITS ) ) >> (SCALEBITS*2);
-    uint32_t db = ( BLUE_COEF  * ( int32_sqr(rgb[BLUE_PIXEL]  - CMAP8_BLUE(i))
-                                << SCALEBITS ) ) >> (SCALEBITS*2);
-
-    uint32_t i_dist = dr + dg + db;
-    if (i_dist < i_mindist) {
-      i_bestmatch = i;
-      i_mindist = i_dist;
-#if 0      
-      printf("+++Change dist to %d RGB cmap %d (%0x, %0x, %0x)\n", 
-             i_dist, i, p_cmap_r[ i ], p_cmap_g[ i ], p_cmap_b[ i ]);
-#endif
-    }
-  }
-
-  if (out_rgb) 
-    {
-      out_rgb[RED_PIXEL]   = CMAP8_RED(i_bestmatch);
-      out_rgb[GREEN_PIXEL] = CMAP8_GREEN(i_bestmatch);
-      out_rgb[BLUE_PIXEL]  = CMAP8_BLUE(i_bestmatch);
-    }
-
-  return i_bestmatch;
-}
-
-/**
-   Get the the rgb value for a given colormap entry for p_vout (which is'
-   assumed to have RGB2 chroma). 
-
-   VLC_FALSE is returned if there was some error.
-*/
-vlc_bool_t
-query_color(const vout_thread_t *p_vout, cmap_t i_cmap,
-            /*out*/ uint8_t *out_rgb) 
-{
-  uint16_t *p_cmap_r;
-  uint16_t *p_cmap_g;
-  uint16_t *p_cmap_b;
-
-  /* Check that we really have RGB2. */
-  
-  if ( !p_vout && p_vout->output.i_chroma  != VLC_FOURCC('R','G','B','2') )
-    return VLC_FALSE;
-
-  if ( !out_rgb ) 
-    return VLC_FALSE;
-
-  p_cmap_r=p_vout->chroma.p_sys->p_rgb_r;
-  p_cmap_g=p_vout->chroma.p_sys->p_rgb_g;
-  p_cmap_b=p_vout->chroma.p_sys->p_rgb_b;
-
-  out_rgb[RED_PIXEL]   = CMAP8_RED(i_cmap);
-  out_rgb[GREEN_PIXEL] = CMAP8_GREEN(i_cmap);
-  out_rgb[BLUE_PIXEL]  = CMAP8_BLUE(i_cmap);
-
-  return VLC_TRUE;
-}
-
-\f
-/* 
- * Local variables:
- *  c-file-style: "gnu"
- *  tab-width: 8
- *  indent-tabs-mode: nil
- * End:
- */
diff --git a/modules/codec/ogt/pixmap.h b/modules/codec/ogt/pixmap.h
deleted file mode 100644 (file)
index 006a398..0000000
+++ /dev/null
@@ -1,164 +0,0 @@
-/*****************************************************************************
- * Common pixel/chroma manipulation routines.
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id: pixmap.h,v 1.6 2004/01/31 23:33:02 rocky Exp $
- *
- * Author: Rocky Bernstein
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-#ifndef PIXMAP_H
-#define PIXMAP_H 
-
-/** Color and transparency of a pixel or a palette (CLUT) entry 
-*/
-typedef union {
-  uint8_t plane[4];
-  struct {
-    uint8_t y;
-    uint8_t v;
-    uint8_t u;
-    uint8_t t;
-  } s;
-} ogt_yuvt_t;
-
-/** An undefined or invalid colormap index. */
-#define INVALID_CMAP_ENTRY -1
-
-/** Type of a palette/colormap index*/
-typedef int16_t cmap_t;
-
-/** Number of entries in RGB palette/colormap*/
-#define CMAP_RGB2_SIZE 256
-
-/**
-   Force v in the range 0..255. In video_chroma/i420_rgb.c, this
-   is macro is called CLIP. FIXME: Combine with that.
-*/
-#define clip_8_bit(v) \
-  ((v < 0) ? 0 : (v > 255) ? 255 : v)
-
-/**
-   Color conversion from
-    http://www.inforamp.net/~poynton/notes/colour_and_gamma/ColorFAQ.html#RTFToC30
-    http://people.ee.ethz.ch/~buc/brechbuehler/mirror/color/ColorFAQ.html
-    Thanks to Billy Biggs <vektor@dumbterm.net> for the pointer and
-    the following conversion.
-    R' = [ 1.1644         0    1.5960 ]   ([ Y' ]   [  16 ])
-    G' = [ 1.1644   -0.3918   -0.8130 ] * ([ Cb ] - [ 128 ])
-    B' = [ 1.1644    2.0172         0 ]   ([ Cr ]   [ 128 ])
-
-  See also vlc/modules/video_chroma/i420_rgb.h and
-  vlc/modules/video_chroma/i420_rgb_c.h for a way to do this in a way
-  more optimized for integer arithmetic. Would be nice to merge the
-  two routines.
-*/
-
-/**
-   Convert a YUV pixel into an RGB pixel.
- */
-static inline void
-yuv2rgb(const ogt_yuvt_t *p_yuv, uint8_t *p_rgb_out )
-{
-  
-  int i_Y  = p_yuv->s.y - 16;
-  int i_Cb = p_yuv->s.v - 128;
-  int i_Cr = p_yuv->s.u - 128;
-  
-  int i_red   = (1.1644 * i_Y) + (1.5960 * i_Cr);
-  int i_green = (1.1644 * i_Y) - (0.3918 * i_Cb) - (0.8130 * i_Cr);
-  int i_blue  = (1.1644 * i_Y) + (2.0172 * i_Cb);
-  
-  i_red   = clip_8_bit( i_red );
-  i_green = clip_8_bit( i_green );
-  i_blue  = clip_8_bit( i_blue );
-  
-#ifdef WORDS_BIGENDIAN
-  *p_rgb_out++ = i_red;
-  *p_rgb_out++ = i_green;
-  *p_rgb_out++ = i_blue;
-#else
-  *p_rgb_out++ = i_blue;
-  *p_rgb_out++ = i_green;
-  *p_rgb_out++ = i_red;
-#endif
-  
-}
-
-/* The byte storage of an RGB pixel. */ 
-#define RGB_SIZE 3
-
-#define GREEN_PIXEL 1
-#ifdef WORDS_BIGENDIAN
-#define RED_PIXEL   0
-#define BLUE_PIXEL  2
-#else
-#define RED_PIXEL   2
-#define BLUE_PIXEL  0
-#endif
-
-/**
-   Store an RGB pixel into the location of p_pixel, taking into
-   account the "Endian"-ness of the underlying machine.
-
-   (N.B. Not sure if I've got this right or this is the right thing
-   to do.)
- */
-static inline void
-put_rgb24_pixel(const uint8_t *rgb, /*out*/ uint8_t *p_pixel)
-{
-#ifdef WORDS_BIGENDIAN
-  *p_pixel++;
-#endif
-  *p_pixel++ = rgb[RED_PIXEL];
-  *p_pixel++ = rgb[GREEN_PIXEL];
-  *p_pixel++ = rgb[BLUE_PIXEL];
-}
-
-/**
-   Find the nearest colormap entry in p_vout (assumed to have RGB2
-   chroma, i.e. 256 RGB 8bpp entries) that is closest in color to p_rgb.  Set
-   out_rgb to the color found and return the colormap index. 
-   INVALID_CMAP_ENTRY is returned if there is some error.
-*/
-cmap_t
-find_cmap_rgb8_nearest(const vout_thread_t *p_vout, const uint8_t *p_rgb,
-                       /*out*/ uint8_t *out_rgb);
-
-/**
-   Get the the rgb value for a given colormap entry for p_vout (which is'
-   assumed to have RGB2 chroma). 
-   
-   VLC_FALSE is returned if there was some error.
-*/
-vlc_bool_t
-query_color(const vout_thread_t *p_vout, cmap_t i_cmap,
-            /*out*/ uint8_t *rgb);
-
-#endif /* PIXMAP_H */
-
-\f
-/* 
- * Local variables:
- *  c-file-style: "gnu"
- *  tab-width: 8
- *  indent-tabs-mode: nil
- * End:
- */
diff --git a/modules/codec/ogt/render.c b/modules/codec/ogt/render.c
deleted file mode 100644 (file)
index 2182477..0000000
+++ /dev/null
@@ -1,1958 +0,0 @@
-/*****************************************************************************
- * render.c : Philips OGT and CVD (VCD Subtitle) blending routines.
- *            stuff from here might be pulled out, abstracted or used
- *            by DVD subtitles.
- *****************************************************************************
- * Copyright (C) 2003, 2004 VideoLAN
- * $Id$
- *
- * Author: Rocky Bernstein <rocky@panix.com>
- *   based on code from: 
- *          Sam Hocevar <sam@zoy.org>
- *          Rudolf Cornelissen <rag.cornelissen@inter.nl.net>
- *          Roine Gustafsson <roine@popstar.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*#define TESTING_TRANSPARENCY 1*/
-
-/*****************************************************************************
- * Preamble
- *****************************************************************************/
-#include <vlc/vlc.h>
-#include <vlc/vout.h>
-#include <vlc/decoder.h>
-
-#include "pixmap.h"
-#include "subtitle.h"
-#include "render.h"
-
-/* We use 4 bits for an transparency value: 0..15, 15 is completely
-   transparent and 0 completely opaque. Note that although SVCD allow
-   8-bits, for these routines pixels should previously have been be
-   scaled down to 4 bits (the range used by DVDs).
-*/
-#define TRANS_BITS (4)
-#define MAX_TRANS  ((1<<TRANS_BITS) - 1) 
-#define TRANS_SCALEDOWN (8-TRANS_BITS)
-
-/* We use a fixed-point arithmetic in scaling ratios so that we
-   can use integer arithmetic and still get fairly precise
-   results. ASCALE is a left shift amount. 
-*/
-#define ASCALE 6  /* 2^6 = 32 */
-
-/* Horrible hack to get dbg_print to do the right thing */
-#define p_dec p_vout
-
-/**
-   Take two 8-bit RGB values and a transparency and do a weighted
-   average of them. The "weight" comes from i_trans which is in the
-   range 0..MAX_TRANS. To have greater precision using integer
-   arithmetic, the RGB values are scaled. The uint16_t cast below is
-   to make sure we don't overflow the product in the multiplication
-
-   (MAX_TRANS - i_trans) is the additive "inverse" of i_trans, i.e.
-   i_trans + (MAX_TRANS - i_trans) = MAX_TRANS. So the resulting sum
-   of rgb1*i_trans + rgb2*(MAX_TRANS-i_trans) will be scaled by
-   MAX_TRANS. To reduce the value back down to 8 bits, we shift by
-   TRANS_BITS, noting that 1 << TRANS_BITS is roughly
-   MAX_TRANS. (Actually it is MAX_TRANS - 1).
-*/
-#define avg_8bit_rgb(rgb_vout, rgb_sub, i_trans)                   \
-{                                                                  \
-   int i;                                                          \
-   for (i=0; i < RGB_SIZE; i++) {                                  \
-   rgb_vout[i] = ( (uint16_t) rgb_vout[i]*(MAX_TRANS-i_trans) +    \
-                   (uint16_t) rgb_sub [i]*i_trans ) >> TRANS_BITS; \
-   }                                                               \
-}
-
-
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-static void BlendI420( vout_thread_t *, picture_t *, const subpicture_t *,
-                        vlc_bool_t );
-static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
-                        const subpicture_t *p_spu, vlc_bool_t b_crop );
-static void BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
-                       const subpicture_t *p_spu, vlc_bool_t b_crop,
-                       vlc_bool_t b_15bpp );
-static void BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
-                        const subpicture_t *p_spu, vlc_bool_t b_crop );
-static void BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
-                        const subpicture_t *p_spu, vlc_bool_t b_crop );
-static void BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
-                        const subpicture_t *p_spu, vlc_bool_t b_crop );
-
-/*****************************************************************************
- * BlendSPU: blend a subtitle into a picture
- *****************************************************************************
-  This blends subtitles (a subpicture) into the underlying
-  picture. Subtitle data has been preprocessed as YUV + transparancy
-  or 4 bytes per pixel with interleaving of rows in the subtitle
-  removed. 
-
- *****************************************************************************/
-void VCDSubBlend( vout_thread_t *p_vout, picture_t *p_pic,
-                  const subpicture_t *p_spu )
-{
-    struct subpicture_sys_t *p_sys = p_spu->p_sys;
-  
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
-              "chroma %x", p_vout->output.i_chroma );
-
-    switch( p_vout->output.i_chroma )
-    {
-        /* I420 target, no scaling */
-        case VLC_FOURCC('I','4','2','0'):
-        case VLC_FOURCC('I','Y','U','V'):
-        case VLC_FOURCC('Y','V','1','2'):
-            BlendI420( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
-            break;
-
-        /* RGB 555 - scaled */
-        case VLC_FOURCC('R','V','1','5'):
-            BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop, 
-                       VLC_TRUE );
-            break;
-          
-        case VLC_FOURCC('R','V','1','6'):
-            BlendRV16( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop,
-                       /* Not sure under what conditions RV16 is really
-                          RV16 and not RV15.
-                        */
-#if 0
-                       VLC_FALSE );
-#else
-                       VLC_TRUE );
-#endif
-           break;
-
-        /* RV24 target, scaling */
-        case VLC_FOURCC('R','V','2','4'):
-            BlendRV24( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
-           break;
-
-        /* RV32 target, scaling */
-        case VLC_FOURCC('R','V','3','2'):
-            BlendRV32( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
-           break;
-
-        /* NVidia overlay, no scaling */
-        case VLC_FOURCC('Y','U','Y','2'):
-            BlendYUY2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
-           break;
-
-        /* Palettized 8 bits per pixel (256 colors). Each
-           pixel is an uint8_t index in the palette
-           Used in ASCII Art. 
-        */
-        case VLC_FOURCC('R','G','B','2'):
-            BlendRGB2( p_vout, p_pic, p_spu, p_spu->p_sys->b_crop );
-          
-           break;
-
-        default:
-            msg_Err( p_vout, "unknown chroma, can't render SPU" );
-            break;
-    }
-}
-
-/* Following functions are local */
-
-/* 
-  YV12 format:  
-
-  All Y samples are found first in memory as an array of bytes
-  (possibly with a larger stride for memory alignment), followed
-  immediately by all Cr (=U) samples (with half the stride of the Y
-  lines, and half the number of lines), then followed immediately by
-  all Cb (=V) samples in a similar fashion.
-*/
-
-static void BlendI420( vout_thread_t *p_vout, picture_t *p_pic,
-                        const subpicture_t *p_spu, vlc_bool_t b_crop )
-{
-  /* Common variables */
-  uint8_t *p_pixel_base_Y, *p_pixel_base_V, *p_pixel_base_U;
-  ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
-
-  int i_x, i_y;
-  vlc_bool_t even_scanline = VLC_FALSE;
-
-  /* Crop-specific */
-  int i_x_start, i_y_start, i_x_end, i_y_end;
-  /* int i=0; */
-
-  const struct subpicture_sys_t *p_sys = p_spu->p_sys;
-  
-  dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
-            "spu width x height: (%dx%d), (x,y)=(%d,%d), yuv pitch (%d,%d,%d)", 
-            p_spu->i_width,  p_spu->i_height, p_spu->i_x, p_spu->i_y,
-            p_pic->Y_PITCH, p_pic->U_PITCH, p_pic->V_PITCH );
-
-  
-  p_pixel_base_Y = p_pic->p[Y_PLANE].p_pixels + p_spu->i_x
-                 + p_pic->p[Y_PLANE].i_pitch * p_spu->i_y;
-  
-  p_pixel_base_U = p_pic->p[U_PLANE].p_pixels + p_spu->i_x/2
-                 + p_pic->p[U_PLANE].i_pitch * p_spu->i_y/2;
-  
-  p_pixel_base_V = p_pic->p[V_PLANE].p_pixels + p_spu->i_x/2
-                 + p_pic->p[V_PLANE].i_pitch * p_spu->i_y/2;
-  
-  i_x_start = p_sys->i_x_start;
-  i_y_start = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_start;
-  
-  i_x_end   = p_sys->i_x_end;
-  i_y_end   = p_pic->p[Y_PLANE].i_pitch * p_sys->i_y_end;
-  
-  p_source = (ogt_yuvt_t *)p_sys->p_data;
-  
-  /* Draw until we reach the bottom of the subtitle */
-  for( i_y = 0; 
-       i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
-       i_y += p_pic->p[Y_PLANE].i_pitch )
-    {
-      uint8_t *p_pixel_base_Y_y = p_pixel_base_Y + i_y;
-      uint8_t *p_pixel_base_U_y = p_pixel_base_U + i_y/4;
-      uint8_t *p_pixel_base_V_y = p_pixel_base_V + i_y/4;
-
-      i_x = 0;
-
-      if ( b_crop ) {
-        if ( i_y > i_y_end ) break;
-        if (i_x_start) {
-          i_x = i_x_start;
-          p_source += i_x_start;
-        }
-      }
-
-      even_scanline = !even_scanline;
-
-      /* Draw until we reach the end of the line */
-      for( ; i_x < p_spu->i_width; i_x++, p_source++ )
-       {
-
-         if( b_crop ) {
-
-            /* FIXME: y cropping should be dealt with outside of this loop.*/
-            if ( i_y < i_y_start) continue;
-
-            if ( i_x > i_x_end )
-           {
-             p_source += p_spu->i_width - i_x;
-              break;
-           }
-          }
-
-#ifdef TESTING_TRANSPARENCY
-          if (p_source->s.t == MAX_TRANS) p_source->s.t >>= 1;
-#endif
-
-         switch( p_source->s.t )
-           {
-           case 0: 
-             /* Completely transparent. Don't change pixel. */
-             break;
-             
-           case MAX_TRANS:
-             {
-               /* Completely opaque. Completely overwrite underlying
-                  pixel with subtitle pixel. */
-               
-               /* This is the location that's going to get changed.*/
-               uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
-               
-               *p_pixel_Y = p_source->plane[Y_PLANE];
-
-               if ( even_scanline && i_x % 2 == 0 ) {
-                 uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2;
-                 uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2;
-                 *p_pixel_U = p_source->plane[U_PLANE];
-                 *p_pixel_V = p_source->plane[V_PLANE];
-               }
-               
-               break;
-             }
-             
-           default:
-             {
-               /* Blend in underlying subtitle pixel. */
-               
-               /* This is the location that's going to get changed. */
-               uint8_t *p_pixel_Y = p_pixel_base_Y_y + i_x;
-
-
-               /* This is the weighted part of the subtitle. The
-                  color plane is 8 bits and transparancy is 4 bits so
-                  when multiplied we get up to 12 bits.
-                */
-               uint16_t i_sub_color_Y = 
-                 (uint16_t) ( p_source->plane[Y_PLANE] *
-                              (uint16_t) (p_source->s.t) );
-
-               /* This is the weighted part of the underlying pixel.
-                  For the same reasons above, the result is up to 12
-                  bits.  However since the transparancies are
-                  inverses, the sum of i_sub_color and i_pixel_color
-                  will not exceed 12 bits.
-               */
-               uint16_t i_pixel_color_Y = 
-                 (uint16_t) ( *p_pixel_Y * 
-                              (uint16_t) (MAX_TRANS - p_source->s.t) ) ;
-               
-               /* Scale the 12-bit result back down to 8 bits. A
-                  precise scaling after adding the two components,
-                  would divide by one less than a power of 2. However
-                  to simplify and speed things we use a power of
-                  2. This means the boundaries (either all
-                  transparent and all opaque) aren't handled properly.
-                  But we deal with them in special cases above. */
-
-               *p_pixel_Y = ( i_sub_color_Y + i_pixel_color_Y ) >> TRANS_BITS;
-
-               if ( even_scanline && i_x % 2 == 0 ) {
-                 uint8_t *p_pixel_U = p_pixel_base_U_y + i_x/2
-                    - p_pic->p[U_PLANE].i_pitch / 2;
-                 uint8_t *p_pixel_V = p_pixel_base_V_y + i_x/2
-                    - p_pic->p[V_PLANE].i_pitch / 2;
-                 uint16_t i_sub_color_U = 
-                   (uint16_t) ( p_source->plane[U_PLANE] *
-                                (uint16_t) (p_source->s.t) );
-                 
-                 uint16_t i_sub_color_V = 
-                   (uint16_t) ( p_source->plane[V_PLANE] *
-                                (uint16_t) (p_source->s.t) );
-                 uint16_t i_pixel_color_U = 
-                   (uint16_t) ( *p_pixel_U * 
-                                (uint16_t) (MAX_TRANS - p_source->s.t) ) ;
-                 uint16_t i_pixel_color_V = 
-                   (uint16_t) ( *p_pixel_V * 
-                                (uint16_t) (MAX_TRANS - p_source->s.t) ) ;
-                 *p_pixel_U = ( i_sub_color_U + i_pixel_color_U )>>TRANS_BITS;
-                 *p_pixel_V = ( i_sub_color_V + i_pixel_color_V )>>TRANS_BITS;
-               }
-               break;
-             }
-             
-           }
-       }
-    }
-}
-
-/*
-
-  YUY2 Format:
-
-  Data is found in memory as an array of bytes in which the first byte
-  contains the first sample of Y, the second byte contains the first
-  sample of Cb (=U), the third byte contains the second sample of Y,
-  the fourth byte contains the first sample of Cr (=V); and so
-  on. Each 32-bit word then contains information for two contiguous
-  horizontal pixels, two 8-bit Y values plus a single Cb and Cr which
-  spans the two pixels.
-*/
-
-#define BYTES_PER_PIXEL 4
-
-static void BlendYUY2( vout_thread_t *p_vout, picture_t *p_pic,
-                        const subpicture_t *p_spu, vlc_bool_t b_crop )
-{
-  /* Common variables */
-  uint8_t *p_pixel_base;
-
-  /* This is the where the subtitle pixels come from */
-  ogt_yuvt_t *p_source = (ogt_yuvt_t *) p_spu->p_sys->p_data;
-
-  ogt_yuvt_t *p_source_end = (ogt_yuvt_t *)p_spu->p_sys->p_data + 
-    (p_spu->i_width * p_spu->i_height);
-
-  uint16_t i_x, i_y;
-
-  /* Make sure we start on a word (4-byte) boundary. */
-  uint16_t i_spu_x = (p_spu->i_x & 0xFFFE) * 2;
-
-  /* Crop-specific */
-  int i_x_start, i_y_start, i_x_end, i_y_end;
-
-  const struct subpicture_sys_t *p_sys = p_spu->p_sys;
-  
-  dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
-            "spu width x height: (%dx%d), (x,y)=(%d,%d), pitch: %d", 
-            p_spu->i_width,  p_spu->i_height, p_spu->i_x, p_spu->i_y,
-            p_pic->p->i_pitch );
-
-  
-  p_pixel_base = p_pic->p->p_pixels + 
-    + ( p_spu->i_y * p_pic->p->i_pitch ) + i_spu_x;
-
-  i_x_start = p_sys->i_x_start;
-  i_y_start = p_sys->i_y_start * p_pic->p->i_pitch;
-  
-  i_x_end   = p_sys->i_x_end;
-  i_y_end   = p_sys->i_y_end   * p_pic->p->i_pitch;
-
-  /* Draw until we reach the bottom of the subtitle */
-  for( i_y = 0; 
-       i_y < p_spu->i_height * p_pic->p[Y_PLANE].i_pitch ;
-       i_y += p_pic->p[Y_PLANE].i_pitch )
-    {
-      uint8_t *p_pixel_base_y = p_pixel_base + i_y;
-
-      i_x = 0;
-
-      if ( b_crop ) {
-        if ( i_y > i_y_end ) break;
-        if (i_x_start) {
-          i_x = i_x_start;
-          p_source += (i_x_start*2);
-        }
-      }
-  
-
-      /* Draw until we reach the end of the line. Each output pixel
-         is a combination of two source pixels. 
-       */
-      for( i_x = 0;  i_x < p_spu->i_width / 2; i_x++, p_source +=2 )
-       {
-          uint16_t i_avg_tr; /* transparancy sort of averaged over 2 pixels*/
-
-          if (p_source > p_source_end-1) {
-            msg_Err( p_vout, "Trying to access beyond subtitle x: %d y: %d",
-                     i_x, i_y);
-            return;
-          }
-
-         if( b_crop ) {
-
-            /* FIXME: y cropping should be dealt with outside of this loop.*/
-            if ( i_y < i_y_start) continue;
-
-            if ( i_x > i_x_end )
-           {
-             p_source += p_spu->i_width - (i_x*2);
-              break;
-           }
-          }
-  
-         
-          /* Favor opaque subtitle pixels. */
-         if ( (p_source->s.t == 0) && (p_source+1)->s.t == MAX_TRANS )
-            i_avg_tr = (p_source+1)->s.t;
-          else if ( (p_source->s.t == MAX_TRANS) && (p_source+1)->s.t == 0 )
-            i_avg_tr = p_source->s.t;
-          else 
-            i_avg_tr = ( p_source->s.t + (p_source+1)->s.t ) / 2;
-          
-#ifdef TESTING_TRANSPARENCY 
-          if (i_avg_tr == MAX_TRANS) i_avg_tr >>= 1;
-#endif
-
-         switch( i_avg_tr )
-           {
-           case 0: 
-             /* Completely transparent. Don't change pixel. */
-             break;
-             
-           case MAX_TRANS:
-             {
-               /* Completely opaque. Completely overwrite underlying
-                  pixel with subtitle pixel. */
-               
-               /* This is the location that's going to get changed. */
-               uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
-               uint8_t i_avg_u;
-               uint8_t i_avg_v;
-
-                /* Favor opaque subtitle pixel. */
-                if (p_source->s.t == MAX_TRANS ) {
-                  i_avg_u = p_source->plane[U_PLANE] ;
-                  i_avg_v = p_source->plane[V_PLANE] ;
-                } else if ( (p_source+1)->s.t == MAX_TRANS ) {
-                  i_avg_u = (p_source+1)->plane[U_PLANE] ;
-                  i_avg_v = (p_source+1)->plane[V_PLANE] ;
-                } else {
-                  i_avg_u = ( p_source->plane[U_PLANE] 
-                              + (p_source+1)->plane[U_PLANE] ) / 2;
-                  i_avg_v = ( p_source->plane[V_PLANE] 
-                              + (p_source+1)->plane[V_PLANE] ) / 2;
-                }
-
-               /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
-               *p_pixel++ = p_source->plane[Y_PLANE] ;
-                *p_pixel++ = i_avg_u;
-               *p_pixel++ = (p_source+1)->plane[Y_PLANE] ;
-                *p_pixel++ = i_avg_v;
-                
-               break;
-             }
-
-           default:
-             {
-               /* Blend in underlying subtitle pixels. */
-               
-               /* This is the location that's going to get changed. */
-               uint8_t *p_pixel = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
-               uint8_t i_avg_u = ( p_source->plane[U_PLANE] 
-                                    + (p_source+1)->plane[U_PLANE] ) / 2;
-               uint8_t i_avg_v = ( p_source->plane[V_PLANE] 
-                                    + (p_source+1)->plane[V_PLANE] ) / 2;
-
-               /* This is the weighted part of the two subtitle
-                  pixels. The color plane is 8 bits and transparancy
-                  is 4 bits so when multiplied we get up to 12 bits.
-                */
-               uint16_t i_sub_color_Y1 = 
-                 (uint16_t) ( p_source->plane[Y_PLANE] *
-                              (uint16_t) (p_source->s.t) );
-
-               uint16_t i_sub_color_Y2 = 
-                 (uint16_t) ( (p_source+1)->plane[Y_PLANE] *
-                              (uint16_t) ((p_source+1)->s.t) );
-
-               /* This is the weighted part of the underlying pixels.
-                  For the same reasons above, the result is up to 12
-                  bits.  However since the transparancies are
-                  inverses, the sum of i_sub_color and i_pixel_color
-                  will not exceed 12 bits.
-               */
-               uint16_t i_sub_color_U = 
-                 (uint16_t) ( i_avg_u * (uint16_t) i_avg_tr );
-               
-               uint16_t i_sub_color_V = 
-                 (uint16_t) ( i_avg_v * (uint16_t) i_avg_tr );
-
-               uint16_t i_pixel_color_Y1 = 
-                 (uint16_t) ( *(p_pixel) * 
-                              (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
-               uint16_t i_pixel_color_Y2 = 
-                 (uint16_t) ( *(p_pixel+2) * 
-                              (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
-               uint16_t i_pixel_color_U = 
-                 (uint16_t) ( *(p_pixel+1) * 
-                              (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
-               uint16_t i_pixel_color_V = 
-                 (uint16_t) ( *(p_pixel+3) * 
-                              (uint16_t) (MAX_TRANS - i_avg_tr) ) ;
-
-               /* draw a two contiguous pixels: 2 Y values, 1 U, and 1 V. */
-
-               /* Scale the 12-bit result back down to 8 bits. A
-                  precise scaling after adding the two components,
-                  would divide by one less than a power of 2. However
-                  to simplify and speed things we use a power of
-                  2. This means the boundaries (either all
-                  transparent and all opaque) aren't handled properly.
-                  But we deal with them in special cases above. */
-
-               *p_pixel++ = ( i_sub_color_Y1 + i_pixel_color_Y1 )>>TRANS_BITS;
-               *p_pixel++ = ( i_sub_color_U + i_pixel_color_U )  >>TRANS_BITS;
-               *p_pixel++ = ( i_sub_color_Y2 + i_pixel_color_Y2 )>>TRANS_BITS;
-               *p_pixel++ = ( i_sub_color_V + i_pixel_color_V )  >>TRANS_BITS;
-               break;
-             }
-           }
-       }
-
-      /* For an odd width source, we'll just have to drop off a pixel. */
-      if (p_spu->i_width % 2) p_source++;
-    }
-}
-
-/**
-   Convert a YUV pixel into a 16-bit RGB 5-5-5 pixel.
-
-   A RGB 5-5-5 pixel looks like this:
-   RGB 5-5-5   bit  (MSB) 7  6   5  4  3  2  1  0 (LSB)
-                 p       ? B4  B3 B2 B1 B0 R4  R3
-                 q      R2 R1  R0 G4 G3 G2 G1  G0
-
-**/
-
-static inline void
-yuv2rgb555(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
-{
-
-  uint8_t rgb[RGB_SIZE];
-
-  yuv2rgb(p_yuv, rgb);
-  
-  /* Scale RGB from 8 bits down to 5. */
-  rgb[RED_PIXEL]   >>= (8-5);
-  rgb[GREEN_PIXEL] >>= (8-5);
-  rgb[BLUE_PIXEL]  >>= (8-5);
-  
-  *p_rgb1 = ( (rgb[BLUE_PIXEL] << 2)&0x7c ) | ( (rgb[RED_PIXEL]>>3) & 0x03 );
-  *p_rgb2 = ( (rgb[RED_PIXEL]  << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
-
-#if 0
-  printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
-         "rgb1: %02x, rgb2 %02x\n",
-         p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
-         rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
-         *p_rgb1, *p_rgb2);
-#endif
-
-}
-
-/**
-   Convert a YUV pixel into a 16-bit RGB 5-6-5 pixel.
-
-   A RGB 5-6-5 pixel looks like this:
-   RGB 5-6-5   bit  (MSB) 7  6   5  4  3  2  1  0 (LSB)
-                 p      B4 B3  B2 B1 B0 R5 R4  R3
-                 q      R2 R1  R0 G4 G3 G2 G1  G0
-
-**/
-
-static inline void
-yuv2rgb565(ogt_yuvt_t *p_yuv, uint8_t *p_rgb1, uint8_t *p_rgb2 )
-{
-
-  uint8_t rgb[RGB_SIZE];
-
-  yuv2rgb(p_yuv, rgb);
-  
-  /* Scale RGB from 8 bits down to 5 or 6 bits. */
-  rgb[RED_PIXEL]   >>= (8-6);
-  rgb[GREEN_PIXEL] >>= (8-5);
-  rgb[BLUE_PIXEL]  >>= (8-5);
-  
-  *p_rgb1 = ( (rgb[BLUE_PIXEL] << 3)&0xF8 ) | ( (rgb[RED_PIXEL]>>3) & 0x07 );
-  *p_rgb2 = ( (rgb[RED_PIXEL]  << 5)&0xe0 ) | ( rgb[GREEN_PIXEL]&0x1f );
-
-#if 0
-  printf("Y,Cb,Cr,T=(%02x,%02x,%02x,%02x), r,g,b=(%d,%d,%d), "
-         "rgb1: %02x, rgb2 %02x\n",
-         p_yuv->s.y, p_yuv->s.u, p_yuv->s.v, p_yuv->s.t,
-         rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL],
-         *p_rgb1, *p_rgb2);
-#endif
-
-}
-
-static inline void
-rv16_pack_blend(uint8_t *p_pixel, ogt_yuvt_t *p_source,  uint8_t *p_rgb1,
-                uint8_t *p_rgb2, vlc_bool_t b_15bpp, uint8_t i_trans, 
-                int a_scale_down )
-{
-  uint8_t rgb_sub[3];
-  uint8_t rgb_vout[RGB_SIZE];
-  int i;
-
-  yuv2rgb(p_source, rgb_sub);
-
-  /* Scale RGB from 8 bits down to 6 or 5. */
-  rgb_sub[GREEN_PIXEL] >>= (8-5);
-  rgb_sub[BLUE_PIXEL]  >>= (8-5);
-
-  rgb_vout[GREEN_PIXEL] = *(p_pixel+1)    & 0x1f;
-  if (b_15bpp) {
-    rgb_sub[RED_PIXEL]   >>= (8-5);
-    rgb_vout[BLUE_PIXEL]  = ((*p_pixel)>>2) & 0x1f;
-    rgb_vout[RED_PIXEL]   = ((*p_pixel & 0x03) << 3) | ((*(p_pixel+1)&0xe0)>>5);
-  } else {
-    rgb_sub[RED_PIXEL]   >>= (8-6);
-    rgb_vout[BLUE_PIXEL]  = ((*p_pixel)>>3) & 0x1f;
-    rgb_vout[RED_PIXEL]   = ((*p_pixel & 0x07) << 3) | ((*(p_pixel+1)&0xe0)>>5);
-  }
-  
-
-#if 0
-  printf("r,g,b=(%d,%d,%d), sub r,g,b=(%d,%d,%d), trans %d, inv_trans %d\n",
-         rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL],
-         rgb_sub[RED_PIXEL], rgb_sub[GREEN_PIXEL], 
-         rgb_sub[BLUE_PIXEL], i_trans, i_inv_trans);
-#endif
-
-#ifdef FIXED_RV16_TRANSPARENCY
-  avg_8bit_rgb(rgb_vout, rgb_sub, i_trans);
-#else 
-  for (i=0; i < RGB_SIZE; i++) {
-    /* For now the Best we can do is fade the color. Picking up 
-       video underneath doesn't work. */
-    /* rgb_vout[i] = ( (uint16_t) rgb_vout[i]*i_inv_trans ) >> TRANS_BITS; */
-    rgb_vout[i] = ( (uint16_t) rgb_sub[i]*i_trans ) >> TRANS_BITS;
-#endif 
-  }
-  
-
-#if 0
-  printf("avg r,g,b=(%d,%d,%d)\n",
-         rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL] );
-#endif
-
-#if 0
-  if (b_15bpp) {
-    *p_rgb1 = ( (rgb_vout[BLUE_PIXEL] << 2)&0x7c )|( (rgb_vout[RED_PIXEL]>>3)&0x03 );
-  } else {
-    *p_rgb1 = ( (rgb_vout[BLUE_PIXEL] << 3)&0xF8 )|( (rgb_vout[RED_PIXEL]>>3)&0x07 );
-  }
-  *p_rgb2 = ( (rgb_vout[RED_PIXEL]  << 5)&0xe0 ) | ( rgb_vout[GREEN_PIXEL]&0x1f );
-#else 
-  *p_rgb1 = (*p_rgb1)+1;
-  *p_rgb2 = (*p_rgb2)+1;
-#endif
-  
-}
-
-#undef BYTES_PER_PIXEL
-#define BYTES_PER_PIXEL 2
-
-static void 
-BlendRV16( vout_thread_t *p_vout, picture_t *p_pic,
-           const subpicture_t *p_spu, vlc_bool_t b_crop,
-           vlc_bool_t b_15bpp )
-{
-    /* Common variables */
-    uint8_t *p_pixel_base;
-    ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
-    ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
-    ogt_yuvt_t *p_source;
-
-    int i_x, i_y;
-    int i_y_src;
-
-    /* Chroma specific */
-    uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
-                            multiplied by 2**ASCALE. */
-    uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
-                            multiplied by 2**ASCALE. */
-
-    int i_width, i_height, i_ytmp, i_ynext;
-
-    /* Crop-specific */
-    int i_x_start, i_y_start, i_x_end, i_y_end;
-
-    struct subpicture_sys_t *p_sys = p_spu->p_sys;
-
-    i_xscale = ( p_vout->output.i_width << ASCALE ) / p_vout->render.i_width;
-    i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
-              "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
-              p_spu->i_width,  p_spu->i_height, 
-              p_vout->output.i_width, p_vout->output.i_height,
-              p_vout->render.i_width, p_vout->render.i_height,
-              i_xscale, i_yscale
-              );
-
-    i_width  = p_spu->i_width  * i_xscale;
-    i_height = p_spu->i_height * i_yscale;
-
-    /* Set where we will start blending subtitle from using
-       the picture coordinates subtitle offsets
-    */
-    p_pixel_base = p_pic->p->p_pixels 
-              + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
-              + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
-
-    i_x_start = p_sys->i_x_start;
-    i_y_start = i_yscale * p_sys->i_y_start;
-    i_x_end   = p_sys->i_x_end;
-    i_y_end   = i_yscale * p_sys->i_y_end;
-
-    p_source = (ogt_yuvt_t *)p_sys->p_data;
-  
-    /* Draw until we reach the bottom of the subtitle */
-    i_y = 0;
-    for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
-         i_y_src += p_spu->i_width )
-    {
-       uint8_t *p_pixel_base_y;
-        i_ytmp = i_y >> ASCALE;
-        i_y += i_yscale;
-       p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
-       i_x = 0;
-
-        if ( b_crop ) {
-          if ( i_y > i_y_end ) break;
-          if (i_x_start) {
-            i_x = i_x_start;
-            p_source += i_x_start;
-          }
-        }
-
-        /* Check whether we need to draw one line or more than one */
-        if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
-        {
-          /* Draw until we reach the end of the line */
-          for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
-            {
-
-#if 0              
-              uint8_t *p=(uint8_t *) p_source;
-              printf("+++ %02x %02x %02x %02x\n", 
-                     p[0], p[1], p[2], p[3]);
-#endif
-    
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-
-             if (p_source >= p_src_end) {
-               msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
-                        i_x, i_y / i_yscale, i_height);
-               return;
-             }
-             
-#ifdef TESTING_TRANSPARENCY
-              if (p_source->s.t == MAX_TRANS) p_source->s.t >>= 1;
-#endif
-
-             switch( p_source->s.t )
-                {
-                case 0:
-                 /* Completely transparent. Don't change pixel. */
-                 break;
-                 
-                case MAX_TRANS:
-                 {
-                   /* Completely opaque. Completely overwrite underlying
-                      pixel with subtitle pixel. */
-               
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-
-                    uint8_t i_rgb1;
-                    uint8_t i_rgb2;
-
-                   /* This is the location that's going to get changed. */
-                   uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
-
-                    if (b_15bpp) 
-                      yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
-                    else 
-                      yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
-
-                    for ( len = i_xlast - i_xdest; len ; len--) {
-                      *p_dest++ = i_rgb1;
-                      *p_dest++ = i_rgb2;
-                    }
-                   break;
-                 }
-
-                default:
-                 {
-                   /* Blend in underlying pixel subtitle pixel. */
-                   
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint8_t i_rgb1;
-                    uint8_t i_rgb2;
-                    uint32_t len     = i_xlast - i_xdest;
-
-                   /* This is the location that's going to get changed. */
-                   uint8_t *p_dest = p_pixel_base_y + i_x * BYTES_PER_PIXEL;
-
-                    for ( len = i_xlast - i_xdest; len ; len--) {
-                      rv16_pack_blend(p_dest, p_source, &i_rgb1, &i_rgb2, 
-                                      b_15bpp, p_source->s.t, TRANS_SCALEDOWN);
-                      *p_dest++ = i_rgb1;
-                      *p_dest++ = i_rgb2;
-                    }
-                   break;
-                 }
-                }
-            }
-        }
-        else
-        {
-            i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
-
-
-            /* Draw until we reach the end of the line */
-            for( ; i_x < p_spu->i_width; i_x++, p_source++ )
-            {
-
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-             
-             if (p_source >= p_src_end) {
-               msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
-                        i_x, i_y / i_yscale, i_height);
-               return;
-             }
-             
-             switch( p_source->s.t )
-                {
-                case 0:
-                   /* Completely transparent. Don't change pixel. */
-                    break;
-
-                case MAX_TRANS: 
-                 {
-                   /* Completely opaque. Completely overwrite underlying
-                      pixel with subtitle pixel. */
-
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-
-                   uint8_t *p_pixel_base_x = p_pixel_base + i_xdest;
-
-                    for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
-                    {
-                     /* This is the location that's going to get changed. */
-                     uint8_t *p_dest = p_pixel_base_x + i_ytmp;
-                      uint8_t i_rgb1, i_rgb2;
-                      if (b_15bpp) 
-                        yuv2rgb555(p_source, &i_rgb1, &i_rgb2);
-                      else 
-                        yuv2rgb565(p_source, &i_rgb1, &i_rgb2);
-
-                      for ( len = i_xlast - i_xdest; len ; len--) {
-                        *p_dest++ = i_rgb1;
-                        *p_dest++ = i_rgb2;
-                      }
-                    }
-                    break;
-                 }
-                default: 
-                  {
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-                    uint8_t i_rgb1, i_rgb2;
-                    for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
-                    {
-                     /* Blend in underlying pixel subtitle pixel. */
-                     uint8_t *p_dest = p_pixel_base + i_ytmp;
-                      for ( len = i_xlast - i_xdest; len ; len--) {
-                        rv16_pack_blend(p_dest, p_source, &i_rgb1, &i_rgb2,
-                                      b_15bpp, p_source->s.t, TRANS_SCALEDOWN);
-                        *p_dest++ = i_rgb1;
-                        *p_dest++ = i_rgb2;
-                      }
-                    }
-                    break;
-                  }
-               }
-           }
-       }
-    }
-}
-
-#undef  BYTES_PER_PIXEL
-#define BYTES_PER_PIXEL 4
-
-static inline void
-rv24_pack_blend(uint8_t *rgb_vout, const uint8_t *rgb_sub,  uint8_t i_trans,  
-                int a_scale_down )
-{
-
-#if 0
-  printf("r,g,b=(%d,%d,%d), source r,g,b=(%d,%d,%d), trans %d\n",
-         rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL],
-         rgb_sub[RED_PIXEL], rgb_sub[GREEN_PIXEL], 
-         rgb_sub[BLUE_PIXEL], i_trans);
-#endif
-
-#ifdef WORDS_BIGENDIAN
-  *rgb_vout++;
-#endif
-
-  avg_8bit_rgb(rgb_vout, rgb_sub, i_trans);
-  
-#if 0
-  printf("avg r,g,b=(%d,%d,%d)\n",
-         rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL] );
-#endif
-
-}
-
-/* 
-  RV24 format??? Is this just for X11? Or just not for Win32? Is this
-  the same as RV32?
-
-  a pixel is represented by 3 bytes containing a red,
-  blue and green sample with blue stored at the lowest address, green
-  next then red. One padding byte is added between pixels. Although
-  this may not be part of a spec, images should be stored with each
-  line padded to a u_int32 boundary. 
-*/
-static void 
-BlendRV24( vout_thread_t *p_vout, picture_t *p_pic,
-            const subpicture_t *p_spu, vlc_bool_t b_crop )
-{
-  /* Common variables */
-  uint8_t *p_pixel_base;
-  ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
-  ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
-  ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
-  
-  int i_x, i_y;
-  int i_y_src;
-  
-  /* Make sure we start on a word (4-byte) boundary. */
-  uint32_t i_spu_x;
-  
-  /* Chroma specific */
-  uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
-                          multiplied by 2**ASCALE. */
-  uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
-                          multiplied by 2**ASCALE. */
-  
-  int i_width, i_height, i_ytmp, i_ynext;
-  
-  /* Crop-specific */
-  int32_t i_x_start, i_y_start, i_x_end, i_y_end;
-  
-  struct subpicture_sys_t *p_sys = p_spu->p_sys;
-  int i_aspect_x, i_aspect_y;
-  
-  vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
-               VOUT_ASPECT_FACTOR, 0 );
-  
-  i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
-    / (i_aspect_y * p_vout->render.i_width);
-  i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
-  
-  dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
-             "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
-             p_spu->i_width,  p_spu->i_height, 
-             p_vout->output.i_width, p_vout->output.i_height,
-             p_vout->render.i_width, p_vout->render.i_height,
-             i_xscale, i_yscale
-             );
-  
-  i_width  = p_spu->i_width  * i_xscale;
-  i_height = p_spu->i_height * i_yscale;
-  
-  /* Set where we will start blending subtitle from using
-     the picture coordinates subtitle offsets.
-  */
-  i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL;
-  
-  p_pixel_base = p_pic->p->p_pixels + i_spu_x
-    + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
-  
-  i_x_start = p_sys->i_x_start;
-  i_y_start = i_yscale * p_sys->i_y_start;
-  i_x_end   = p_sys->i_x_end;
-  i_y_end   = i_yscale * p_sys->i_y_end;
-  
-  p_source = (ogt_yuvt_t *)p_sys->p_data;
-  
-  /* Draw until we reach the bottom of the subtitle */
-  i_y = 0;
-  for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
-       i_y_src += p_spu->i_width )
-    {
-      uint8_t *p_pixel_base_y;
-      i_ytmp = i_y >> ASCALE;
-      i_y += i_yscale;
-      p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
-      i_x = 0;
-      
-      if ( b_crop ) {
-        if ( i_y > i_y_end ) break;
-        if (i_x_start) {
-          i_x = i_x_start;
-          p_source += i_x_start;
-        }
-      }
-      
-      /* Check whether we need to draw one line or more than one */
-      if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
-        {
-          /* Draw until we reach the end of the line */
-          for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
-            {
-              
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-              
-             if (p_source >= p_src_end) {
-               msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
-                        i_x, i_y / i_yscale, i_height);
-               return;
-             }
-             
-#ifdef TESTING_TRANSPARENCY
-              if (p_source->s.t == MAX_TRANS) p_source->s.t >>= 2;
-#endif
-
-             switch( p_source->s.t )
-                {
-                case 0:
-                 /* Completely transparent. Don't change pixel. */
-                 break;
-                 
-                case MAX_TRANS:
-                 {
-                   /* Completely opaque. Completely overwrite underlying
-                      pixel with subtitle pixel. */
-                    
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-                    
-                    uint8_t rgb[RGB_SIZE];
-                    
-                   /* This is the location that's going to get changed. */
-                   uint8_t *p_dest = p_pixel_base_y + i_xdest;
-                    
-                    yuv2rgb(p_source, rgb);
-                    
-                    for ( len = i_xlast - i_xdest; len ; len--) {
-                      put_rgb24_pixel(rgb, p_dest);
-                      p_dest += BYTES_PER_PIXEL;
-                    }
-                    
-                  default:
-                    {
-                      /* Blend in underlying pixel subtitle pixel. */
-                      
-                      uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                           * BYTES_PER_PIXEL );
-                      uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                           * BYTES_PER_PIXEL );
-                      uint32_t len     = i_xlast - i_xdest * BYTES_PER_PIXEL;
-                      
-                      /* To be able to scale correctly for full
-                         opaqueness, we add 1 to the transparency.
-                         This means transparency value 0 won't be
-                         completely transparent which is not correct.
-                         But that's handled in a special case above
-                         anyway. */
-                      
-                      /* This is the location that's going to get changed. */
-                      uint8_t *p_dest = p_pixel_base_y + i_xdest;
-                      uint8_t rgb[RGB_SIZE];
-                      
-                      yuv2rgb(p_source, rgb);
-
-                      for ( len = i_xlast - i_xdest; len ; len--) {
-                        rv24_pack_blend(p_dest, rgb, p_source->s.t,
-                                        TRANS_SCALEDOWN);
-                        p_dest += BYTES_PER_PIXEL;
-                      }
-                      break;
-                    }
-                  }
-                }
-            }
-        } 
-        else
-        {
-            i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
-
-
-            /* Draw until we reach the end of the line */
-            for( ; i_x < p_spu->i_width; i_x++, p_source++ )
-            {
-
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-             
-             if (p_source >= p_src_end) {
-               msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
-                        i_x, i_y / i_yscale, i_height);
-               return;
-             }
-             
-             switch( p_source->s.t )
-                {
-                case 0:
-                   /* Completely transparent. Don't change pixel. */
-                    break;
-
-                case MAX_TRANS: 
-                 {
-                   /* Completely opaque. Completely overwrite underlying
-                      pixel with subtitle pixel. */
-
-                   /* This is the location that's going to get changed. */
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-
-                    uint8_t rgb[RGB_SIZE];
-
-                    yuv2rgb(p_source, rgb); 
-
-                    for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
-                    {
-                      /* Completely opaque. Completely overwrite underlying
-                         pixel with subtitle pixel. */
-                      
-                      /* This is the location that's going to get changed. */
-                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
-                      
-                      for ( len = i_xlast - i_xdest; len ; len--) {
-                        put_rgb24_pixel(rgb, p_dest);
-                        p_dest += BYTES_PER_PIXEL;
-                      }
-                    }
-                    break;
-                 }
-                default: 
-                  {
-                    
-
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-                    uint8_t  rgb[RGB_SIZE];
-
-                    yuv2rgb(p_source, rgb);
-
-                    for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
-                    {
-                     /* Blend in underlying pixel subtitle pixel. */
-                     
-                      /* This is the location that's going to get changed. */
-                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
-
-                     /* To be able to scale correctly for full opaqueness, we
-                        add 1 to the alpha.  This means alpha value 0 won't
-                        be completely transparent and is not correct, but
-                        that's handled in a special case above anyway. */
-
-                      for ( len = i_xlast - i_xdest; len ; len--) {
-                        rv24_pack_blend(p_dest, rgb, p_source->s.t,
-                                        TRANS_SCALEDOWN);
-                        p_dest += BYTES_PER_PIXEL;
-                      }
-                    }
-                    break;
-                  }
-                }
-            }
-       }
-    }
-}
-
-#undef  BYTES_PER_PIXEL
-#define BYTES_PER_PIXEL 4
-
-/* 
-  RV32 format??? Is this just for X11? Or just not for Win32? Is this
-  the same as RV24?
-
-  RV32 format: a pixel is represented by 4 bytes containing a red,
-  blue and green sample with blue stored at the lowest address, green
-  next then red. One padding byte is added between pixels. Although
-  this may not be part of a spec, images should be stored with each
-  line padded to a u_int32 boundary. 
-*/
-static void 
-BlendRV32( vout_thread_t *p_vout, picture_t *p_pic,
-            const subpicture_t *p_spu, vlc_bool_t b_crop )
-{
-    /* Common variables */
-    uint8_t *p_pixel_base;
-    ogt_yuvt_t *p_src_start = (ogt_yuvt_t *)p_spu->p_sys->p_data;
-    ogt_yuvt_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
-    ogt_yuvt_t *p_source; /* This is the where the subtitle pixels come from */
-
-    int i_x, i_y;
-    int i_y_src;
-
-    /* Make sure we start on a word (4-byte) boundary. */
-    uint32_t i_spu_x;
-
-    /* Chroma specific */
-    uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
-                            multiplied by 2**ASCALE. */
-    uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
-                            multiplied by 2**ASCALE. */
-
-    int i_width, i_height, i_ytmp, i_ynext;
-
-    /* Crop-specific */
-    int32_t i_x_start, i_y_start, i_x_end, i_y_end;
-
-    struct subpicture_sys_t *p_sys = p_spu->p_sys;
-    int i_aspect_x, i_aspect_y;
-
-    vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
-                VOUT_ASPECT_FACTOR, 0 );
-
-    i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
-      / (i_aspect_y * p_vout->render.i_width);
-    i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
-              "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
-              p_spu->i_width,  p_spu->i_height, 
-              p_vout->output.i_width, p_vout->output.i_height,
-              p_vout->render.i_width, p_vout->render.i_height,
-              i_xscale, i_yscale
-              );
-
-    i_width  = p_spu->i_width  * i_xscale;
-    i_height = p_spu->i_height * i_yscale;
-
-    /* Set where we will start blending subtitle from using
-       the picture coordinates subtitle offsets.
-    */
-    i_spu_x = ((p_spu->i_x * i_xscale) >> ASCALE) * BYTES_PER_PIXEL; 
-
-    p_pixel_base = p_pic->p->p_pixels + i_spu_x
-              + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
-
-    i_x_start = p_sys->i_x_start;
-    i_y_start = i_yscale * p_sys->i_y_start;
-    i_x_end   = p_sys->i_x_end;
-    i_y_end   = i_yscale * p_sys->i_y_end;
-
-    p_source = (ogt_yuvt_t *)p_sys->p_data;
-  
-    /* Draw until we reach the bottom of the subtitle */
-    i_y = 0;
-    for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
-         i_y_src += p_spu->i_width )
-    {
-       uint8_t *p_pixel_base_y;
-        i_ytmp = i_y >> ASCALE;
-        i_y += i_yscale;
-       p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
-       i_x = 0;
-
-        if ( b_crop ) {
-          if ( i_y > i_y_end ) break;
-          if (i_x_start) {
-            i_x = i_x_start;
-            p_source += i_x_start;
-          }
-        }
-
-        /* Check whether we need to draw one line or more than one */
-        if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
-        {
-          /* Draw until we reach the end of the line */
-          for( ; i_x < p_spu->i_width;  i_x++, p_source++ )
-            {
-
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-
-             if (p_source >= p_src_end) {
-               msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
-                        i_x, i_y / i_yscale, i_height);
-               return;
-             }
-             
-             switch( p_source->s.t )
-                {
-                case 0:
-                 /* Completely transparent. Don't change pixel. */
-                 break;
-                 
-                default:
-                case MAX_TRANS:
-                 {
-                   /* Completely opaque. Completely overwrite underlying
-                      pixel with subtitle pixel. */
-
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-
-                    uint8_t rgb[RGB_SIZE];
-
-                   /* This is the location that's going to get changed. */
-                   uint8_t *p_dest = p_pixel_base_y + i_xdest;
-
-                    yuv2rgb(p_source, rgb);
-
-                    for ( len = i_xlast - i_xdest; len ; len--) {
-                      *p_dest++ = rgb[BLUE_PIXEL];
-                      *p_dest++ = rgb[GREEN_PIXEL];
-                      *p_dest++ = rgb[RED_PIXEL];
-                      *p_dest++;
-                    }
-
-#ifdef TRANSPARENCY_FINISHED
-                  default:
-                    {
-                      /* Blend in underlying pixel subtitle pixel. */
-                      
-                      uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                           * BYTES_PER_PIXEL );
-                      uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                           * BYTES_PER_PIXEL );
-                      uint32_t len     = i_xlast - i_xdest;
-
-                      /* To be able to scale correctly for full opaqueness, we
-                         add 1 to the alpha.  This means alpha value 0 won't
-                         be completely transparent and is not correct, but
-                         that's handled in a special case above anyway. */
-                      
-                      uint8_t i_destalpha = MAX_TRANS - p_source->s.t;
-                      uint8_t rgb[RGB_SIZE];
-
-                      /* This is the location that's going to get changed. */
-                      uint8_t *p_dest = p_pixel_base_y + i_xdest;
-                      
-                      yuv2rgb(p_source, rgb);
-                      rv32_pack_blend(p_dest, rgb, dest_alpha, 
-                                      TRANS_SCALEDOWN);
-
-                      for ( len = i_xlast - i_xdest; len ; len--) {
-                        *p_dest++ = rgb[BLUE_PIXEL];
-                        *p_dest++ = rgb[GREEN_PIXEL];
-                        *p_dest++ = rgb[RED_PIXEL];
-                        *p_dest++;
-                      }
-                      break;
-                    }
-#endif /*TRANSPARENCY_FINISHED*/
-                  }
-                }
-            }
-        } 
-        else
-        {
-            i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
-
-
-            /* Draw until we reach the end of the line */
-            for( ; i_x < p_spu->i_width; i_x++, p_source++ )
-            {
-
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-             
-             if (p_source >= p_src_end) {
-               msg_Err( p_vout, "Trying to access beyond subtitle %dx%d %d",
-                        i_x, i_y / i_yscale, i_height);
-               return;
-             }
-             
-             switch( p_source->s.t )
-                {
-                case 0:
-                   /* Completely transparent. Don't change pixel. */
-                    break;
-
-                default:
-                case MAX_TRANS: 
-                 {
-                   /* Completely opaque. Completely overwrite underlying
-                      pixel with subtitle pixel. */
-
-                   /* This is the location that's going to get changed. */
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-
-                    uint8_t rgb[RGB_SIZE];
-
-                    yuv2rgb(p_source, rgb); 
-
-                    for(  ; i_ytmp < i_ynext ; i_ytmp += p_pic->p->i_pitch )
-                    {
-                      /* Completely opaque. Completely overwrite underlying
-                         pixel with subtitle pixel. */
-                      
-                      /* This is the location that's going to get changed. */
-                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
-                      
-                      for ( len = i_xlast - i_xdest; len ; len--) {
-                        put_rgb24_pixel(rgb, p_dest);
-                      }
-                    }
-                    break;
-                 }
-#ifdef TRANSPARENCY_FINISHED
-                default: 
-                  {
-                    
-
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-                    uint8_t rgb[RGB_SIZE];
-
-                    yuv2rgb(p_source, rgb);
-
-                    for(  ; i_ytmp < i_ynext ; y_ytmp += p_pic->p->i_pitch )
-                    {
-                     /* Blend in underlying pixel subtitle pixel. */
-                     
-                      /* This is the location that's going to get changed. */
-                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
-
-                     /* To be able to scale correctly for full opaqueness, we
-                        add 1 to the alpha.  This means alpha value 0 won't
-                        be completely transparent and is not correct, but
-                        that's handled in a special case above anyway. */
-
-                      uint8_t i_destalpha = MAX_TRANS - p_source->s.t;
-                      rv32_pack_blend(p_dest, rgb, dest_alpha,
-                                      TRANS_SCALEDOWN);
-                    }
-                    break;
-#endif /*TRANSPARENCY_FINISHED*/
-               }
-           }
-       }
-    }
-}
-
-/* 4-entry array of colormap indices */
-static  uint8_t cmap[NUM_SUBTITLE_COLORS];
-
-/* Actual RGB values for above; this is used in blending.*/
-static uint8_t cmap_rgb[NUM_SUBTITLE_COLORS][RGB_SIZE];
-
-/*
-  Return the colormap index for the average of i_pixel and a subtitle
-  pixel whose subtitle palette entry is i_cmap. 
- */
-static inline cmap_t
-avg_rgb2(const vout_thread_t *p_vout, uint8_t i_pixel, uint8_t i_trans, 
-         int i_cmap, mtime_t i_pts)
-{
-  uint8_t rgb_vout[RGB_SIZE];
-
-  /* Cache the average of a vout colormap entry and a subtitle palette
-     entry. There are not too many of these 256*4 = 1024.
-   */
-  static cmap_t avg_cache[CMAP_RGB2_SIZE][NUM_SUBTITLE_COLORS];
-
-  /* subtitle palettes might change between two subtitles. i_last_pts
-     will be used to figure out if the subtitle has changed, and
-     we have to invalidate the cache. */
-  static mtime_t i_last_pts = -1;
-
-  if (i_pts != i_last_pts) 
-    {
-      /* Hack: We rely on the fact that INVALID_CMAP_ENTRY is repeated
-         0xFF.
-       */
-      memset(avg_cache, 0xFF, sizeof(avg_cache));
-      i_last_pts = i_pts;
-    }
-
-  if ( avg_cache[i_pixel][i_cmap] != INVALID_CMAP_ENTRY ) 
-    return avg_cache[i_pixel][i_cmap];
-
-  if ( !query_color(p_vout, i_pixel, rgb_vout) ) return INVALID_CMAP_ENTRY;
-
-  avg_8bit_rgb(rgb_vout, cmap_rgb[i_cmap], i_trans);
-
-#if 0
- {
-  uint8_t rgb_approx[RGB_SIZE];
-
-  avg_cache[i_pixel][i_cmap] = 
-    find_cmap_rgb8_nearest(p_vout, rgb_vout, rgb_approx);
-  printf(
-         "cmap old %0x avg approx 0%x sub: %d sub=(%0x, %0x, %0x) "
-         "approx=(%0x, %0x, %0x) avg vout=(%0x, %0x, %0x)\n", 
-         i_pixel, avg_cache[i_pixel][i_cmap], i_cmap,
-         cmap_rgb[i_cmap][RED_PIXEL], cmap_rgb[i_cmap][GREEN_PIXEL], 
-         cmap_rgb[i_cmap][BLUE_PIXEL],
-         rgb_approx[RED_PIXEL], rgb_approx[GREEN_PIXEL], rgb_approx[BLUE_PIXEL],
-         rgb_vout[RED_PIXEL], rgb_vout[GREEN_PIXEL], rgb_vout[BLUE_PIXEL]);
- }  
-#else 
-  avg_cache[i_pixel][i_cmap] = 
-    find_cmap_rgb8_nearest(p_vout, rgb_vout, NULL);
-#endif
-  return avg_cache[i_pixel][i_cmap];
-}
-
-#undef  BYTES_PER_PIXEL
-#define BYTES_PER_PIXEL 1
-
-static void 
-BlendRGB2( vout_thread_t *p_vout, picture_t *p_pic,
-            const subpicture_t *p_spu, vlc_bool_t b_crop )
-{
-    /* Common variables */
-    uint8_t *p_pixel_base;
-    uint8_t *p_src_start = (uint8_t *)p_spu->p_sys->p_data;
-    uint8_t *p_src_end   = &p_src_start[p_spu->i_height * p_spu->i_width];
-    uint8_t *p_source; /* This is the where the subtitle pixels come from */
-    int i;
-
-    int i_x, i_y;
-    int i_y_src;
-
-    /* Chroma specific */
-    uint32_t i_xscale;   /* Amount we scale subtitle in the x direction,
-                            multiplied by 2**ASCALE. */
-    uint32_t i_yscale;   /* Amount we scale subtitle in the y direction.
-                            multiplied by 2**ASCALE. */
-
-    int i_width, i_height, i_ytmp;
-
-    /* Crop-specific */
-    int i_x_start, i_y_start, i_x_end, i_y_end;
-
-    struct subpicture_sys_t *p_sys = p_spu->p_sys;
-    int i_aspect_x, i_aspect_y;
-
-    vlc_reduce( &i_aspect_x, &i_aspect_y, p_vout->render.i_aspect,
-                VOUT_ASPECT_FACTOR, 0 );
-    
-    i_xscale = (( p_vout->output.i_width << ASCALE ) * i_aspect_x)
-      / (i_aspect_y * p_vout->render.i_width);
-    i_yscale = ( p_vout->output.i_height << ASCALE ) / p_vout->render.i_height;
-
-    dbg_print( (DECODE_DBG_CALL|DECODE_DBG_RENDER), 
-              "spu: %dx%d, scaled: %dx%d, vout render: %dx%d, scale %dx%d", 
-              p_spu->i_width,  p_spu->i_height, 
-              p_vout->output.i_width, p_vout->output.i_height,
-              p_vout->render.i_width, p_vout->render.i_height,
-              i_xscale, i_yscale
-              );
-
-    i_width  = p_spu->i_width  * i_xscale;
-    i_height = p_spu->i_height * i_yscale;
-
-
-    /** FIXME: do once per subtitle in subtitle processing, not here
-        each time we render.  */
-    /* Find a corresponding colormap entries for our palette entries. */
-    for( i = 0; i < NUM_SUBTITLE_COLORS; i++ )
-    {
-
-      if ( p_sys->p_palette[i].s.t != 0 ) {
-        uint8_t rgb[RGB_SIZE]; 
-        yuv2rgb(&(p_sys->p_palette[i]), rgb);
-        cmap[i] = 
-          find_cmap_rgb8_nearest(p_vout, rgb, cmap_rgb[i]);
-        dbg_print( (DECODE_DBG_RENDER), 
-                   "palette %d RGB=(%0x, %0x, %0x)\n", i,
-                   rgb[RED_PIXEL], rgb[GREEN_PIXEL], rgb[BLUE_PIXEL]);
-      }
-    }
-
-    /* Set where we will start blending subtitle from using
-       the picture coordinates subtitle offsets
-    */
-    p_pixel_base = p_pic->p->p_pixels 
-              + ( (p_spu->i_x * i_xscale) >> ASCALE ) * BYTES_PER_PIXEL
-              + ( (p_spu->i_y * i_yscale) >> ASCALE ) * p_pic->p->i_pitch;
-
-    i_x_start = p_sys->i_x_start;
-    i_y_start = i_yscale * p_sys->i_y_start;
-    i_x_end   = p_sys->i_x_end;
-    i_y_end   = i_yscale * p_sys->i_y_end;
-
-    p_source = (uint8_t *)p_sys->p_data;
-  
-    /* Draw until we reach the bottom of the subtitle */
-    i_y = 0;
-    for( i_y_src = 0 ; i_y_src < p_spu->i_height * p_spu->i_width; 
-         i_y_src += p_spu->i_width )
-      {
-       uint8_t *p_pixel_base_y;
-        i_ytmp = i_y >> ASCALE;
-        i_y += i_yscale;
-       p_pixel_base_y = p_pixel_base + (i_ytmp * p_pic->p->i_pitch);
-       i_x = 0;
-
-        if ( b_crop ) {
-          if ( i_y > i_y_end ) break;
-          if (i_x_start) {
-            i_x = i_x_start;
-            p_source += i_x_start;
-          }
-        }
-        
-        /* Check whether we need to draw one line or more than one */
-        if( i_ytmp + 1 >= ( i_y >> ASCALE ) )
-        {
-
-          /* Draw until we reach the end of the line */
-          for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
-            {
-              ogt_yuvt_t p_yuvt;
-
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-              
-              if (p_source >= p_src_end) {
-                msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
-                         i_x, i_y / i_yscale, i_height);
-                return;
-              }
-              
-              p_yuvt = p_sys->p_palette[*p_source & 0x3];
-
-#ifdef TESTING_TRANSPARENCY
-              if (p_yuvt.s.t == MAX_TRANS) p_yuvt.s.t >>= 1;
-#endif
-
-              switch ( p_yuvt.s.t ) 
-                {
-                case 0:
-                 /* Completely transparent. Don't change pixel. */
-#if 0
-                  printf(" "); /*++++*/
-#endif
-                  break;
-                case MAX_TRANS: 
-                  {
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    /* This is the pixel that's going to change;*/
-                    uint8_t *p_dest = p_pixel_base_y + i_xdest;
-                    memset( p_dest, cmap[*p_source & 0x3], i_xlast - i_xdest );
-#if 0
-                    printf("%1d", *p_source); /*++++*/
-#endif
-                    break;
-                  }
-                default:
-                  {
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    /* This is the pixel that's going to change;*/
-                    uint8_t *p_pixel = p_pixel_base_y + i_xdest;
-                    uint32_t len     = i_xlast - i_xdest;
-
-#if FULL_TRANSPARENCY
-                    /* This is what should be done, but it may be too
-                      slow.  */
-                    for ( len = i_xlast - i_xdest -1; len >= 0; len-- ) 
-                      {
-                        cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t,
-                                                  *p_source, p_sys->i_pts);
-                                                  
-                        if (i_cmap != INVALID_CMAP_ENTRY) 
-                          *p_pixel= (uint8_t) i_cmap;
-                        p_pixel++;
-                      }
-#else
-                    cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t,
-                                              *p_source, p_sys->i_pts);
-                    if (i_cmap != INVALID_CMAP_ENTRY) 
-                      memset(p_pixel, i_cmap, len);
-#endif 
-
-#if 0
-                    printf("%1d", *p_source); /*++++*/
-#endif
-                  }
-                }
-            }
-#if 0
-          printf("\n"); /*++++*/
-#endif
-        } else {
-          /* Have to scale over many lines. */
-          int i_yreal = p_pic->p->i_pitch * i_ytmp;
-          int i_ynext = p_pic->p->i_pitch * i_y >> ASCALE;
-
-           /* Draw until we reach the end of the line */
-           for( ; i_x < p_spu->i_width; i_x ++, p_source++ )
-             {
-              ogt_yuvt_t p_yuvt = p_sys->p_palette[*p_source & 0x3];
-
-              if( b_crop ) {
-                
-                /* FIXME: y cropping should be dealt with outside of this 
-                   loop.*/
-                if ( i_y < i_y_start) continue;
-                
-                if ( i_x > i_x_end )
-                  {
-                    p_source += p_spu->i_width - i_x;
-                    break;
-                  }
-              }
-              
-              if (p_source >= p_src_end) {
-                msg_Err( p_vout, "trying to access beyond subtitle %dx%d %d",
-                         i_x, i_y / i_yscale, i_height);
-                return;
-              }
-              
-#ifdef TESTING_TRANSPARENCY
-              if (p_yuvt.s.t == MAX_TRANS) p_yuvt.s.t >>= 1;
-#endif
-              switch ( p_yuvt.s.t ) 
-                {
-                case 0:
-                 /* Completely transparent. Don't change pixel. */
-#if 0
-                  printf(" "); /*++++*/
-#endif
-                  break;
-                case MAX_TRANS: 
-                  {
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    uint32_t len     = i_xlast - i_xdest;
-#if 0
-                    printf("%1d", *p_source); /*++++*/
-#endif
-                    for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
-                         i_ytmp += p_pic->p->i_pitch ) {
-                      uint8_t *p_dest = p_pixel_base + i_ytmp + i_xdest;
-                      memset( p_dest, cmap[*p_source & 0x3], len );
-                    }
-                    break;
-                  }
-                default:
-                  {
-                    uint32_t i_xdest = ( ((i_x*i_xscale) >> ASCALE) 
-                                         * BYTES_PER_PIXEL );
-                    uint32_t i_xlast = ( (((i_x+1)*i_xscale) >> ASCALE)
-                                         * BYTES_PER_PIXEL );
-                    int32_t len = i_xlast - i_xdest;
-#if 0
-                    printf("%1d", *p_source); /*++++*/
-#endif
-
-                    for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
-                         i_ytmp += p_pic->p->i_pitch ) {
-                      /* This is the pixel that's going to change;*/
-                      uint8_t *p_pixel = p_pixel_base + i_ytmp + i_xdest;
-
-#if FULL_TRANSPARENCY
-                    /* This is what should be done, but it may be too
-                      slow.  */
-                      for ( len = i_xlast - i_xdest -1; len >= 0; len-- ) 
-                        {
-                          cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, 
-                                                    p_yuvt.s.t, *p_source, 
-                                                    p_sys->i_pts);
-                          if (i_cmap != INVALID_CMAP_ENTRY) 
-                            *p_pixel= (uint8_t) i_cmap;
-                          p_pixel++;
-                        }
-#else
-                    cmap_t i_cmap  = avg_rgb2(p_vout, *p_pixel, p_yuvt.s.t, 
-                                              *p_source, p_sys->i_pts);
-                    if (i_cmap != INVALID_CMAP_ENTRY) 
-                      memset(p_pixel, i_cmap, len);
-#endif 
-
-                    }
-                  }
-                }
-             }
-        }
-      }
-}
-
-\f
-/* 
- * Local variables:
- *  c-file-style: "gnu"
- *  tab-width: 8
- *  indent-tabs-mode: nil
- * End:
- */
diff --git a/modules/codec/ogt/render.h b/modules/codec/ogt/render.h
deleted file mode 100644 (file)
index 736b41b..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/*****************************************************************************
- * render.h : Common SVCD and CVD rendering routine(s).
- *****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: render.h,v 1.3 2004/01/21 04:45:47 rocky Exp $
- *
- * Author: Rocky Bernstein
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-/*****************************************************************************
- * Prototypes
- *****************************************************************************/
-void VCDSubBlend  ( vout_thread_t *, picture_t *, const subpicture_t * );
-
diff --git a/modules/codec/ogt/subtitle.h b/modules/codec/ogt/subtitle.h
deleted file mode 100644 (file)
index 4e55300..0000000
+++ /dev/null
@@ -1,209 +0,0 @@
-/*****************************************************************************
- * subtitle.h : Common SVCD and CVD subtitles header
- *****************************************************************************
- * Copyright (C) 2003,2004 VideoLAN
- * $Id$
- *
- * Author: Rocky Bernstein
- *   based on code from:
- *       Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
- *       Sam Hocevar <sam@zoy.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-#include "pixmap.h"
-
-#define DECODE_DBG_EXT         1 /* Calls from external routines */
-#define DECODE_DBG_CALL        2 /* all calls */
-#define DECODE_DBG_PACKET      4 /* packet assembly info */
-#define DECODE_DBG_IMAGE       8 /* image bitmaps */
-#define DECODE_DBG_TRANSFORM  16 /* bitmap transformations */
-#define DECODE_DBG_RENDER     32 /* rendering information */
-#define DECODE_DBG_PNG        64 /* Extract subtitles to PNG files. */
-#define DECODE_DBG_INFO      128
-
-#define DEBUG_TEXT N_( \
-     "If nonzero, this gives additional debug information." \
-     )
-
-#define DEBUG_LONGTEXT N_( \
-    "This integer when viewed in binary is a debugging mask\n" \
-    "external call          1\n" \
-    "all calls              2\n" \
-    "packet assembly info   4\n" \
-    "image bitmaps          8\n" \
-    "image transformations 16\n" \
-    "rendering information 32\n" \
-    "extract subtitles     64\n" \
-    "misc info            128\n" )
-
-#define SUB_ASPECT_RATIO_TEXT N_("Subtitle aspect-ratio correction")
-#define SUB_ASPECT_RATIO_LONGTEXT N_( \
-    "Use this to force the subtitle aspect ratio. If you give a null string " \
-    "the right value will be determined automatically. Usually this is what " \
-    "you want. For OGT and CVD subtitles this undoes the effect " \
-    "of the underlying video scaling. And using a value of 1 will cause " \
-    "no correction; subtitles will be scaled with the same aspect " \
-    "ratio as as the underlying video (which not correct for OGT or " \
-    "CVD subtitles). You can also force another ratio by giving a pair of " \
-    "integers x:y where y should between x and twice x. For example 4:3, or " \
-    "16:9. Alternatively, you can give a float value expressing pixel " \
-    "squareness. For example 1.25 or 1.3333 which mean the same thing as " \
-    "4:3 and 16:9 respectively." \
-    )
-
-#define DURATION_SCALE_TEXT N_("Factor to increase subtitle display interval")
-#define DURATION_SCALE_LONGTEXT N_( \
-  "If you find you need extra time for reading subtitles, " \
-  "you can set this higher and it will multiply the display " \
-  "time by that amount. Use 0 to mean until the next " \
-  "subtitle.")
-
-#define HORIZONTAL_CORRECT \
-  N_("Add this to starting horizontal position of subtitle.")
-#define HORIZONTAL_CORRECT_LONGTEXT N_( \
-  "If you need to adjust the subtitle starting position horizontally, " \
-  "set this. Negative values shift left and positive values right. 0 would " \
-  "be no deviation from where the position specified in the subtitle." \
-  )
-
-#define VERTICAL_CORRECT \
-  N_("Add this to starting vertical position of subtitle.")
-#define VERTICAL_CORRECT_LONGTEXT N_( \
-  "If you need to adjust the subtitle starting position vertically, " \
-  "set this. Negative values shift up, positive values down. 0 would " \
-  "be no deviation from where the position specified in the subtitle." \
-  )
-
-#define DECODE_DEBUG 1
-#if DECODE_DEBUG
-#define dbg_print(mask, s, args...) \
-   if (p_sys && p_sys->i_debug & mask) \
-     msg_Dbg(p_dec, "%s: "s, __func__ , ##args)
-#else
-#define dbg_print(mask, s, args...)
-#endif
-
-#define LOG_ERR(args...)  msg_Err( p_input, args )
-#define LOG_WARN(args...) msg_Warn( p_input, args )
-
-#define GETINT16(p) ( (p[0] <<  8) +   p[1] )  ; p +=2;
-
-#define GETINT32(p) ( (p[0] << 24) +  (p[1] << 16) +    \
-                      (p[2] <<  8) +  (p[3]) ) ; p += 4;
-
-
-/* The number of color palette entries allowed in a subtitle. */
-#define NUM_SUBTITLE_COLORS 4
-
-typedef enum  {
-  SUBTITLE_BLOCK_EMPTY,
-  SUBTITLE_BLOCK_PARTIAL,
-  SUBTITLE_BLOCK_COMPLETE
-} packet_state_t;
-
-/* The byte storage used by one pixel */
-#define PIXEL_SIZE 4
-
-/* Size in bytes of YUV portion above. */
-#define YUV_SIZE 3
-
-
-
-/* Transparency plane. NOTE: see vlc_video.h for V_PLANE */
-#define T_PLANE  V_PLANE+1
-
-struct decoder_sys_t
-{
-  int            i_debug; /* debugging mask */
-  mtime_t        i_pts;   /* Start PTS of subtitle block */
-  int            i_spu;
-  packet_state_t state;   /* data-gathering state for this subtitle */
-
-  uint16_t       i_image; /* image number in the subtitle stream; 0 is the
-                             first one. */
-  uint8_t        i_packet;/* packet number for above image number; 0 is the
-                             first one. */
-  block_t        *p_block;/* Bytes of the packet. */
-
-  uint8_t buffer[65536 + 20 ]; /* we will never overflow more than 11
-                                  bytes if I'm right */
-  int     b_packetizer;
-  int     i_spu_size;     /* goal for subtitle_data_pos while gathering,
-                             size of used subtitle_data later */
-  vout_thread_t *p_vout;
-
-  int i_subpic_channel;   /* Subpicture channel in which subtitles will
-                             be written */
-
-  /* FIXME: Remove this? */
-  uint8_t *subtitle_data;   /* buffer used to accumulate data from
-                               successive packets in the same subtitle */
-  int subtitle_data_size;   /* size of the allocated subtitle_data */
-
-  /* Move into subpicture_sys_t? */
-  uint16_t i_image_offset;      /* offset from subtitle_data to compressed
-                                   image data */
-  int i_image_length;           /* size of the compressed image data */
-  int first_field_offset;       /* offset of even raster lines. Used
-                                   only for CVD. */
-  int second_field_offset;      /* offset of odd raster lines */
-  int metadata_offset;          /* offset to data describing the image */
-  int metadata_length;          /* length of metadata */
-
-  int subtitle_data_pos;    /* where to write next chunk */
-
-  mtime_t i_duration;   /* how long to display the image, 0 stands
-                           for "until next subtitle" */
-
-  uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
-                                    image when displayed */
-  uint16_t i_width, i_height;    /* dimensions in pixels of image */
-
-  ogt_yuvt_t p_palette[NUM_SUBTITLE_COLORS];  /* Palette of colors used
-                                                 in subtitle */
-
-
-  ogt_yuvt_t p_palette_highlight[NUM_SUBTITLE_COLORS]; /* Only used
-                                                          for CVD */
-
-  uint8_t i_options;
-  uint8_t i_options2;
-  uint8_t i_cmd;
-  uint32_t i_cmd_arg;
-};
-
-struct subpicture_sys_t
-{
-  int     i_debug;              /* debugging mask */
-  mtime_t i_pts;                /* presentation timestamp */
-
-  uint8_t *p_data;             /* Image data one byte T, Y, U, V */
-
-
-  /* Link to our input */
-  vlc_object_t * p_input;
-
-  /* Cropping properties */
-  vlc_mutex_t  lock;
-  vlc_bool_t   b_crop;
-  unsigned int i_x_start, i_y_start, i_x_end, i_y_end;
-
-  /* This is only used for color palette Chromas like RGB2. */
-  ogt_yuvt_t p_palette[NUM_SUBTITLE_COLORS];  /* Palette of colors used
-                                                 in subtitle */
-
-};
diff --git a/modules/codec/ogt/write_png.c b/modules/codec/ogt/write_png.c
deleted file mode 100644 (file)
index 009044a..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/*****************************************************************************
- * Dump an Image to a Portable Network Graphics (PNG) file
- ****************************************************************************
-  Copyright (C) 2004 VideoLAN
-  Author: Rocky Bernstein
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-#include "config.h"
-#ifdef HAVE_LIBPNG
-
-#include <stdio.h>
-#include <stdlib.h>
-#include "write_png.h"
-#include <setjmp.h>
-
-typedef void (*snapshot_messenger_t)(char *message);
-
-#define _(x) x
-
-/*
- *   Error functions for use as callbacks by the png libraries
- */
-
-void error_msg(char *message) 
-{
-  printf("error: %s\n", message);
-}
-
-void warning_msg(char *message) 
-{
-  printf("warning: %s\n", message);
-}
-
-static snapshot_messenger_t error_msg_cb = error_msg;
-static snapshot_messenger_t warning_msg_cb  = warning_msg;
-
-static void 
-user_error_fn(png_structp png_ptr, png_const_charp error_msg)
-{
-
-  if(error_msg_cb) {
-    char uerror[4096]; 
-
-    memset(&uerror, 0, sizeof(uerror));
-    sprintf(uerror, _("Error: %s\n"), error_msg);
-    error_msg_cb(uerror);
-  }
-}
-
-static void 
-user_warning_fn(png_structp png_ptr, png_const_charp warning_msg)
-{
-  if(error_msg_cb) {
-    char uerror[4096];
-    
-    memset(&uerror, 0, sizeof(uerror));
-    sprintf(uerror, _("Error: %s\n"), warning_msg);
-    warning_msg_cb(uerror);
-  }
-}
-
-/* 
-   Dump an image to a Portable Network Graphics (PNG) file. File_name
-   is where the file goes, i_height and i_width are the height and
-   width in pixels of the image. The data for the image is stored as a
-   linear array of one byte for each of red, green, and blue
-   components of an RGB pixel. Thus row[i] will begin at rgb_image +
-   i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image +
-   i*(i_width*3) + 1.
-   
- */
-void 
-write_png(const char *file_name, png_uint_32 i_height, png_uint_32 i_width,
-         void *rgb_image, /*in*/ png_text *text_ptr, int i_text_count )
-{
-  FILE *fp;
-  png_structp png_ptr;
-  png_infop info_ptr;
-  png_color_8 sig_bit;
-  png_bytep *row_pointers;
-
-  unsigned int i,j;
-
-  /* open the file */
-  fp = fopen(file_name, "wb");
-  if (fp == NULL)
-    return;
-  
-  /* Create and initialize the png_struct with the desired error handler
-   * functions.  If you want to use the default stderr and longjump method,
-   * you can supply NULL for the last three parameters.  We also check that
-   * the library version is compatible with the one used at compile time,
-   * in case we are using dynamically linked libraries.  REQUIRED.
-   */
-  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL,
-                                   user_error_fn, user_warning_fn);
-  
-  if (png_ptr == NULL)
-    {
-      fclose(fp);
-      return;
-    }
-  
-  /* Allocate/initialize the image information data.  REQUIRED */
-  info_ptr = png_create_info_struct(png_ptr);
-  if (info_ptr == NULL)
-    {
-      fclose(fp);
-      png_destroy_write_struct(&png_ptr,  (png_infopp)NULL);
-      return;
-    }
-  
-  /* Set error handling.  REQUIRED if you aren't supplying your own
-   * error handling functions in the png_create_write_struct() call.
-   */
-  if (setjmp(png_ptr->jmpbuf))
-    {
-      /* If we get here, we had a problem writing the file */
-      fclose(fp);
-      png_destroy_write_struct(&png_ptr,  (png_infopp) &info_ptr);
-      return;
-   }
-
-   /* Set up the output control using standard C streams. This
-      is required. */
-   png_init_io(png_ptr, fp);
-
-   /* Set the image information here.  i_width and i_height are up to 2^31,
-    * bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
-    * the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
-    * PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
-    * or PNG_COLOR_TYPE_RGB_ALPHA.  interlace is either PNG_INTERLACE_NONE or
-    * PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
-    * currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
-    */
-   png_set_IHDR(png_ptr, info_ptr, i_width, i_height, 8, PNG_COLOR_TYPE_RGB,
-               PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, 
-               PNG_FILTER_TYPE_BASE);
-
-   /* For color images: */
-   sig_bit.red   = 8;
-   sig_bit.green = 8;
-   sig_bit.blue  = 8;
-
-   if (text_ptr)
-     png_set_text(png_ptr, info_ptr, text_ptr, i_text_count);
-
-   /* Write the file header information.  REQUIRED */
-   png_write_info(png_ptr, info_ptr);
-
-   /* Once we write out the header, the compression type on the text
-    * chunks gets changed to PNG_TEXT_COMPRESSION_NONE_WR or
-    * PNG_TEXT_COMPRESSION_zTXt_WR, so it doesn't get written out again
-    * at the end.
-    */
-
-   /* Shift the pixels up to a legal bit depth and fill in
-    * as appropriate to correctly scale the image.
-    */
-   png_set_shift(png_ptr, &sig_bit);
-
-   /* pack pixels into bytes */
-   png_set_packing(png_ptr);
-
-   row_pointers = png_malloc(png_ptr, i_height*sizeof(png_bytep *));
-   for (i=0, j=0; i<i_height; i++, j+=i_width*3) {
-     row_pointers[i] = rgb_image + j; 
-   }
-   
-   png_set_rows   (png_ptr, info_ptr, row_pointers);
-   png_write_image(png_ptr, row_pointers);
-
-   /* You can write optional chunks like tEXt, zTXt, and tIME at the end
-    * as well.
-    */
-
-   /* It is REQUIRED to call this to finish writing the rest of the file */
-   png_write_end(png_ptr, info_ptr);
-
-   /* if you allocated any text comments, free them here */
-   /* free image data if allocated. */
-
-   /* clean up after the write, and free any memory allocated */
-   png_destroy_info_struct(png_ptr, &info_ptr);
-
-   /* clean up after the write, and free any memory allocated */
-   png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
-
-   fclose(fp);
-
-   return;
-}
-
-#ifdef STANDALONE
-int
-main(int argc, char **argv) 
-{
-  char image_data[3*16 * 3*16 * 3];
-  int i,j,k,l,m;
-  char r,g,b,t, or,og,ob;
-
-  or=0x00; og=0xFF; ob=0x0;
-  m=0;
-  for (i=0; i<3; i++) {
-    t=or; or=og; og=ob; ob=t;
-    for (j=0; j<16; j++) {
-      r=or; g=og; b=ob;
-      for (k=0; k<3; k++) {
-       for (l=0; l<16; l++) {
-         image_data[m++]=r;
-         image_data[m++]=g;
-         image_data[m++]=b;
-       }
-       t=r; r=g; g=b; b=t;
-      }
-    }
-  }
-  
-  write_png("/tmp/pngtest.png", 3*16, 3*16, (void *) image_data) ;
-  return 0;
-}
-#endif /*STANDALONE*/
-
-#endif /*HAVE_LIBPNG*/
diff --git a/modules/codec/ogt/write_png.h b/modules/codec/ogt/write_png.h
deleted file mode 100644 (file)
index df9945f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*****************************************************************************
- * Dump an Image to a Portable Network Graphics (PNG) file
- ****************************************************************************
-  Copyright (C) 2004 VideoLAN
-  Author: Rocky Bernstein
-  This program is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation; either version 2 of the License, or
-  (at your option) any later version.
-  This program is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-  You should have received a copy of the GNU General Public License
-  along with this program; if not, write to the Free Software
-  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
- *****************************************************************************/
-
-#include <png.h>
-
-/* 
-   Dump an image to a Portable Network Graphics (PNG) file. File_name
-   is where the file goes, i_height and i_width are the height and
-   width in pixels of the image. The data for the image is stored as a
-   linear array RGB pixel entries: one byte for each of red, green,
-   and blue component. Thus row[i] will begin at rgb_image +
-   i*(i_width*3) and the blue pixel at image[i][0] would be rgb_image
-   + i*(i_width*3) + 1.
-
-   text_ptr contains comments that can be written to the image. It can
-   be null. i_text_count is the number of entries in text_ptr.
-   
- */
-void write_png(const char *file_name, png_uint_32 i_height, 
-              png_uint_32 i_width, void *rgb_image, 
-              /*in*/ png_text *text_ptr, int i_text_count );
-
diff --git a/modules/codec/svcdsub.c b/modules/codec/svcdsub.c
new file mode 100644 (file)
index 0000000..7e00ea0
--- /dev/null
@@ -0,0 +1,510 @@
+/*****************************************************************************
+ * svcdsub.c : Overlay Graphics Text (SVCD subtitles) decoder
+ *****************************************************************************
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id$
+ *
+ * Authors: Rocky Bernstein
+ *          Gildas Bazin <gbazin@videolan.org>
+ *          Julio Sanchez Fernandez (http://subhandler.sourceforge.net)
+ *          Laurent Aimar <fenrir@via.ecp.fr>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ *****************************************************************************/
+
+#define DEBUG_SVCD 1
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include "vlc_bits.h"
+
+/*****************************************************************************
+ * Module descriptor.
+ *****************************************************************************/
+static int  DecoderOpen   ( vlc_object_t * );
+static int  PacketizerOpen( vlc_object_t * );
+static void DecoderClose  ( vlc_object_t * );
+
+vlc_module_begin();
+    set_description( _("Philips OGT (SVCD subtitle) decoder") );
+    set_capability( "decoder", 50 );
+    set_callbacks( DecoderOpen, DecoderClose );
+
+    add_submodule();
+    set_description( _("Philips OGT (SVCD subtitle) packetizer") );
+    set_capability( "packetizer", 50 );
+    set_callbacks( PacketizerOpen, DecoderClose );
+vlc_module_end();
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static subpicture_t *Decode( decoder_t *, block_t ** );
+static block_t *Packetize  ( decoder_t *, block_t ** );
+static block_t *Reassemble ( decoder_t *, block_t * );
+static void ParseHeader( decoder_t *, block_t * );
+static subpicture_t *DecodePacket( decoder_t *, block_t * );
+static void RenderImage( decoder_t *, block_t *, subpicture_region_t * );
+
+#define GETINT16(p) ( (p[0] <<  8) +   p[1] )  ; p +=2;
+
+#define GETINT32(p) ( (p[0] << 24) +  (p[1] << 16) +    \
+                      (p[2] <<  8) +  (p[3]) ) ; p += 4;
+
+#define SUBTITLE_BLOCK_EMPTY 0
+#define SUBTITLE_BLOCK_PARTIAL 1
+#define SUBTITLE_BLOCK_COMPLETE 2
+
+struct decoder_sys_t
+{
+  int      b_packetizer;
+
+  int      i_state;    /* data-gathering state for this subtitle */
+
+  block_t  *p_spu;   /* Bytes of the packet. */
+
+  uint16_t i_image;  /* image number in the subtitle stream */
+  uint8_t  i_packet; /* packet number for above image number */
+
+  int     i_spu_size;     /* goal for subtitle_data_pos while gathering,
+                             size of used subtitle_data later */
+
+  uint16_t i_image_offset;      /* offset from subtitle_data to compressed
+                                   image data */
+  int i_image_length;           /* size of the compressed image data */
+  int second_field_offset;      /* offset of odd raster lines */
+  int metadata_offset;          /* offset to data describing the image */
+  int metadata_length;          /* length of metadata */
+
+  mtime_t i_duration;   /* how long to display the image, 0 stands
+                           for "until next subtitle" */
+
+  uint16_t i_x_start, i_y_start; /* position of top leftmost pixel of
+                                    image when displayed */
+  uint16_t i_width, i_height;    /* dimensions in pixels of image */
+
+  uint8_t p_palette[4][4];       /* Palette of colors used in subtitle */
+};
+
+/*****************************************************************************
+ * DecoderOpen: open/initialize the svcdsub decoder.
+ *****************************************************************************/
+static int DecoderOpen( vlc_object_t *p_this )
+{
+    decoder_t     *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC( 'o','g','t',' ' ) )
+    {
+        return VLC_EGENERIC;
+    }
+
+    p_dec->p_sys = p_sys = malloc( sizeof( decoder_sys_t ) );
+
+    p_sys->b_packetizer  = VLC_FALSE;
+    p_sys->i_image       = -1;
+
+    p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
+    p_sys->p_spu   = NULL;
+
+    es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'o','g','t',' ' ) );
+
+    p_dec->pf_decode_sub = Decode;
+    p_dec->pf_packetize  = Packetize;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * PacketizerOpen: open/initialize the svcdsub packetizer.
+ *****************************************************************************/
+static int PacketizerOpen( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+
+    if( DecoderOpen( p_this ) != VLC_SUCCESS ) return VLC_EGENERIC;
+
+    p_dec->p_sys->b_packetizer = VLC_TRUE;
+
+    return VLC_SUCCESS;
+}
+
+/*****************************************************************************
+ * DecoderClose: closes the svcdsub decoder/packetizer.
+ *****************************************************************************/
+void DecoderClose( vlc_object_t *p_this )
+{
+    decoder_t     *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    if( p_sys->p_spu ) block_ChainRelease( p_sys->p_spu );
+    free( p_sys );
+}
+
+/*****************************************************************************
+ * Decode:
+ *****************************************************************************/
+static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block )
+{
+    block_t *p_block, *p_spu;
+
+    if( pp_block == NULL || *pp_block == NULL ) return NULL;
+
+    p_block = *pp_block;
+    *pp_block = NULL;
+
+    if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
+
+    /* Parse and decode */
+    return DecodePacket( p_dec, p_spu );
+}
+
+/*****************************************************************************
+ * Packetize:
+ *****************************************************************************/
+static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
+{
+    block_t *p_block, *p_spu;
+
+    if( pp_block == NULL || *pp_block == NULL ) return NULL;
+
+    p_block = *pp_block;
+    *pp_block = NULL;
+
+    if( !(p_spu = Reassemble( p_dec, p_block )) ) return NULL;
+
+    p_spu->i_dts = p_spu->i_pts;
+    p_spu->i_length = 0;
+
+    return p_spu;
+}
+
+/*****************************************************************************
+ Reassemble:
+
+ The data for single screen subtitle may come in one of many
+ non-contiguous packets of a stream. This routine is called when the
+ next packet in the stream comes in. The job of this routine is to
+ parse the header, if this is the beginning, and combine the packets
+ into one complete subtitle unit.
+
+ If everything is complete, we will return a block. Otherwise return
+ NULL.
+
+
+ The format of the beginning of the subtitle packet that is used here.
+
+   size    description
+   -------------------------------------------
+   byte    subtitle channel (0..7) in bits 0-3
+   byte    subtitle packet number of this subtitle image 0-N,
+           if the subtitle packet is complete, the top bit of the byte is 1.
+   uint16  subtitle image number
+
+ *****************************************************************************/
+#define SPU_HEADER_LEN 5
+
+static block_t *Reassemble( decoder_t *p_dec, block_t *p_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p_buffer;
+    uint16_t i_expected_image;
+    uint8_t  i_packet, i_expected_packet;
+
+    if( p_block->i_buffer < SPU_HEADER_LEN )
+    {
+        msg_Dbg( p_dec, "invalid packet header (size %d < %d)" ,
+                 p_block->i_buffer, SPU_HEADER_LEN );
+        block_Release( p_block );
+        return NULL;
+    }
+
+    p_buffer = p_block->p_buffer;
+
+    if( p_sys->i_state == SUBTITLE_BLOCK_EMPTY )
+    {
+        i_expected_image  = p_sys->i_image + 1;
+        i_expected_packet = 0;
+    }
+    else
+    {
+        i_expected_image  = p_sys->i_image;
+        i_expected_packet = p_sys->i_packet + 1;
+    }
+
+    p_buffer += 2;
+
+    if( *p_buffer & 0x80 )
+    {
+        p_sys->i_state = SUBTITLE_BLOCK_COMPLETE;
+        i_packet       = *p_buffer++ & 0x7F;
+    }
+    else
+    {
+        p_sys->i_state = SUBTITLE_BLOCK_PARTIAL;
+        i_packet       = *p_buffer++;
+    }
+
+    p_sys->i_image = GETINT16(p_buffer);
+
+    if( p_sys->i_image != i_expected_image )
+    {
+        msg_Warn( p_dec, "expected subtitle image %u but found %u",
+                  i_expected_image, p_sys->i_image );
+    }
+
+    if( i_packet != i_expected_packet )
+    {
+        msg_Warn( p_dec, "expected subtitle image packet %u but found %u",
+                  i_expected_packet, i_packet );
+    }
+
+    p_block->p_buffer += SPU_HEADER_LEN;
+    p_block->i_buffer -= SPU_HEADER_LEN;
+
+    p_sys->i_packet = i_packet;
+    /* First packet in the subtitle block */
+    if( !p_sys->i_packet ) ParseHeader( p_dec, p_block );
+
+    block_ChainAppend( &p_sys->p_spu, p_block );
+
+    if( p_sys->i_state == SUBTITLE_BLOCK_COMPLETE )
+    {
+        block_t *p_spu = block_ChainGather( p_sys->p_spu );
+
+        if( p_spu->i_buffer != p_sys->i_spu_size )
+        {
+            msg_Warn( p_dec, "SPU packets size=%d should be %d",
+                      p_spu->i_buffer, p_sys->i_spu_size );
+        }
+
+        msg_Dbg( p_dec, "subtitle packet complete, size=%d", p_spu->i_buffer);
+
+        p_sys->i_state = SUBTITLE_BLOCK_EMPTY;
+        p_sys->p_spu = 0;
+        return p_spu;
+    }
+
+    return NULL;
+}
+
+/******************************************************************************
+  The format is roughly as follows (everything is big-endian):
+   size     description
+   -------------------------------------------
+   byte     subtitle channel (0..7) in bits 0-3 
+   byte     subtitle packet number of this subtitle image 0-N,
+            if the subtitle packet is complete, the top bit of the byte is 1.
+   u_int16  subtitle image number
+   u_int16  length in bytes of the rest
+   byte     option flags, unknown meaning except bit 3 (0x08) indicates
+            presence of the duration field
+   byte     unknown 
+   u_int32  duration in 1/90000ths of a second (optional), start time
+            is as indicated by the PTS in the PES header
+   u_int32  xpos
+   u_int32  ypos
+   u_int32  width (must be even)
+   u_int32  height (must be even)
+   byte[16] palette, 4 palette entries, each contains values for
+            Y, U, V and transparency, 0 standing for transparent
+   byte     command,
+            cmd>>6==1 indicates shift
+            (cmd>>4)&3 is direction from, (0=top,1=left,2=right,3=bottom)
+   u_int32  shift duration in 1/90000ths of a second
+   u_int16  offset of odd-numbered scanlines - subtitle images are 
+            given in interlace order
+   byte[]   limited RLE image data in interlace order (0,2,4... 1,3,5) with
+            2-bits per palette number
+******************************************************************************/
+static void ParseHeader( decoder_t *p_dec, block_t *p_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p = p_block->p_buffer;
+    uint8_t i_options, i_options2, i_cmd, i_cmd_arg;
+    int i;
+
+    p_sys->i_spu_size = GETINT16(p);
+    i_options  = *p++;
+    i_options2 = *p++;
+
+    if( i_options & 0x08 ) { p_sys->i_duration = GETINT32(p); }
+    else p_sys->i_duration = 0; /* Ephemer subtitle */
+    p_sys->i_duration *= 100 / 9;
+
+    p_sys->i_x_start = GETINT16(p);
+    p_sys->i_y_start = GETINT16(p);
+    p_sys->i_width   = GETINT16(p);
+    p_sys->i_height  = GETINT16(p);
+
+    for( i = 0; i < 4; i++ )
+    {
+        p_sys->p_palette[i][0] = *p++;
+        p_sys->p_palette[i][1] = *p++;
+        p_sys->p_palette[i][2] = *p++;
+        p_sys->p_palette[i][3] = *p++;
+    }
+
+    i_cmd = *p++;
+    /* We do not really know this, FIXME */
+    if( i_cmd ) {i_cmd_arg = GETINT32(p);}
+
+    /* Actually, this is measured against a different origin, so we have to
+     * adjust it */
+    p_sys->second_field_offset = GETINT16(p);
+    p_sys->i_image_offset  = p - p_block->p_buffer;
+    p_sys->i_image_length  = p_sys->i_spu_size - p_sys->i_image_offset;
+    p_sys->metadata_length = p_sys->i_image_offset;
+
+#ifdef DEBUG_SVCD
+    msg_Dbg( p_dec, "x-start: %d, y-start: %d, width: %d, height %d, "
+             "spu size: %d, duration: %lu (d:%d p:%d)",
+             p_sys->i_x_start, p_sys->i_y_start, 
+             p_sys->i_width, p_sys->i_height, 
+             p_sys->i_spu_size, (long unsigned int) p_sys->i_duration,
+             p_sys->i_image_length, p_sys->i_image_offset);
+
+    for( i = 0; i < 4; i++ )
+    {
+        msg_Dbg( p_dec, "palette[%d]= T: %2x, Y: %2x, u: %2x, v: %2x", i,
+                 p_sys->p_palette[i][3], p_sys->p_palette[i][0], 
+                 p_sys->p_palette[i][1], p_sys->p_palette[i][2] );
+    }
+#endif
+}
+
+/*****************************************************************************
+ * DecodePacket: parse and decode an SPU packet
+ *****************************************************************************
+ * This function parses and decodes an SPU packet and, if valid, returns a
+ * subpicture.
+ *****************************************************************************/
+static subpicture_t *DecodePacket( decoder_t *p_dec, block_t *p_data )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    subpicture_t  *p_spu;
+    subpicture_region_t *p_region;
+    video_format_t fmt;
+    int i;
+
+    /* Allocate the subpicture internal data. */
+    p_spu = p_dec->pf_spu_buffer_new( p_dec );
+    if( !p_spu ) return NULL;
+
+    p_spu->i_x = p_sys->i_x_start;
+    p_spu->i_x = p_spu->i_x * 3 / 4; /* FIXME: use aspect ratio for x? */
+    p_spu->i_y = p_sys->i_y_start;
+    p_spu->i_start = p_data->i_pts;
+    p_spu->i_stop  = p_data->i_pts + p_sys->i_duration;
+    p_spu->b_ephemer = VLC_TRUE;
+
+    /* Create new SPU region */
+    memset( &fmt, 0, sizeof(video_format_t) );
+    fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
+    fmt.i_aspect = VOUT_ASPECT_FACTOR;
+    fmt.i_width = fmt.i_visible_width = p_sys->i_width;
+    fmt.i_height = fmt.i_visible_height = p_sys->i_height;
+    fmt.i_x_offset = fmt.i_y_offset = 0;
+    p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
+    if( !p_region )
+    {
+        msg_Err( p_dec, "cannot allocate SPU region" );
+        //goto error;
+    }
+
+    p_spu->p_region = p_region;
+    p_region->i_x = p_region->i_y = 0;
+
+    /* Build palette */
+    fmt.p_palette->i_entries = 4;
+    for( i = 0; i < fmt.p_palette->i_entries; i++ )
+    {
+        fmt.p_palette->palette[i][0] = p_sys->p_palette[i][0];
+        fmt.p_palette->palette[i][1] = p_sys->p_palette[i][1];
+        fmt.p_palette->palette[i][2] = p_sys->p_palette[i][2];
+        fmt.p_palette->palette[i][3] = p_sys->p_palette[i][3];
+    }
+
+    RenderImage( p_dec, p_data, p_region );
+
+    return p_spu;
+}
+
+/*****************************************************************************
+ * ParseImage: parse the image part of the subtitle
+ *****************************************************************************
+ This part parses the subtitle graphical data and renders it.
+
+ 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.
+
+ However we'll transform this so that that the RLE is expanded and
+ interlacing will also be removed.
+ *****************************************************************************/
+static void RenderImage( decoder_t *p_dec, block_t *p_data,
+                         subpicture_region_t *p_region )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    uint8_t *p_dest = p_region->picture.Y_PIXELS;
+    int i_field;            /* The subtitles are interlaced */
+    int i_row, i_column;    /* scanline row/column number */
+    uint8_t i_color, i_count;
+    bs_t bs;
+
+    bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset,
+             p_data->i_buffer - p_sys->i_image_offset );
+
+    for( i_field = 0; i_field < 2; i_field++ )
+    {
+        for( i_row = i_field; i_row < p_sys->i_height; i_row += 2 )
+        {
+            for( i_column = 0; i_column < p_sys->i_width; i_column++ )
+            {
+                i_color = bs_read( &bs, 2 );
+                if( i_color == 0 && (i_count = bs_read( &bs, 2 )) )
+                {
+                    i_count = __MIN( i_count, p_sys->i_width - i_column );
+                    memset( &p_dest[i_row * p_region->picture.Y_PITCH +
+                                    i_column], 0, i_count + 1 );
+                    i_column += i_count;
+                    continue;
+                }
+
+                p_dest[i_row * p_region->picture.Y_PITCH + i_column] = i_color;
+            }
+
+            bs_align( &bs );
+        }
+
+        /* odd field */
+        bs_init( &bs, p_data->p_buffer + p_sys->i_image_offset +
+                 p_sys->second_field_offset,
+                 p_data->i_buffer - p_sys->i_image_offset -
+                 p_sys->second_field_offset );
+    }
+}