]> git.sesse.net Git - vlc/blobdiff - modules/codec/ogt/cvd.c
* ALL: separation of the SPU engine from the VOUT.
[vlc] / modules / codec / ogt / cvd.c
index e48d8131f9fa40325dddfaece5726f5b68847987..46abe55ca2552dfe8e2f5b8cf87bf177f53927c7 100644 (file)
@@ -1,8 +1,8 @@
 /*****************************************************************************
  * cvd.c : CVD Subtitle decoder thread
  *****************************************************************************
- * Copyright (C) 2003 VideoLAN
- * $Id: cvd.c,v 1.1 2003/12/28 04:51:52 rocky Exp $
+ * Copyright (C) 2003, 2004 VideoLAN
+ * $Id$
  *
  * Authors: Rocky Bernstein
  *   based on code from:
 #include "cvd.h"
 #include "common.h"
 
-#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" \
-    "misc info             32\n" )
-
 /*****************************************************************************
  * Module descriptor.
  *****************************************************************************/
-static int  DecoderOpen   ( vlc_object_t * );
+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( DecoderOpen, VCDSubClose );
+    set_callbacks( VCDSubOpen, VCDSubClose );
 
     add_integer ( MODULE_STRING "-debug", 0, NULL,
-                  N_("set debug mask for additional debugging."),
-                  N_(DEBUG_LONGTEXT), VLC_TRUE );
+                  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") );
@@ -71,18 +75,17 @@ vlc_module_end();
  *****************************************************************************/
 
 static block_t *Reassemble( decoder_t *, block_t ** );
-static void     Decode   ( decoder_t *, block_t ** );
+static subpicture_t *Decode( decoder_t *, block_t ** );
 static block_t *Packetize( decoder_t *, block_t ** );
 
-
 /*****************************************************************************
- * DecoderOpen
+ * VCDSubOpen
  *****************************************************************************
  * Tries to launch a decoder and return score so that the interface is able
  * to chose.
  *****************************************************************************/
 static int
-DecoderOpen( vlc_object_t *p_this )
+VCDSubOpen( vlc_object_t *p_this )
 {
     decoder_t     *p_dec = (decoder_t*)p_this;
     decoder_sys_t *p_sys;
@@ -124,7 +127,7 @@ static int PacketizerOpen( vlc_object_t *p_this )
 {
     decoder_t *p_dec = (decoder_t*)p_this;
 
-    if( DecoderOpen( p_this ) )
+    if( VCDSubOpen( p_this ) )
     {
         return VLC_EGENERIC;
     }
@@ -136,11 +139,12 @@ static int PacketizerOpen( vlc_object_t *p_this )
 /*****************************************************************************
  * Decode:
  *****************************************************************************/
-static void
+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) , "");
 
@@ -152,6 +156,12 @@ Decode ( decoder_t *p_dec, block_t **pp_block )
 
         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 );
 
@@ -161,6 +171,7 @@ Decode ( decoder_t *p_dec, block_t **pp_block )
         VCDSubInitSubtitleBlock ( p_sys );
     }
 
+    return NULL;
 }
 
 /*****************************************************************************
@@ -186,30 +197,20 @@ Packetize( decoder_t *p_dec, block_t **pp_block )
 
 /* following functions are local */
 
-#define SPU_HEADER_LEN 5
+#define SPU_HEADER_LEN 1
 
 /*****************************************************************************
  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.
+ 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.
 
-
- 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 )
@@ -217,8 +218,6 @@ 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 )
     {
@@ -237,71 +236,72 @@ Reassemble( decoder_t *p_dec, block_t **pp_block )
 
     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);
+    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);
 
-    if( config_GetInt( p_dec, "spu-channel" ) != p_buffer[1] )
-      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;
-    }
+    /* Attach to our input thread and see if subtitle is selected. */
+    {
+        vlc_object_t * p_input;
+        vlc_value_t val;
 
-    p_buffer += 2;
+        p_input = vlc_object_find( p_dec, VLC_OBJECT_INPUT, FIND_PARENT );
 
-    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++;
-    }
+        if( !p_input ) return NULL;
 
-    p_sys->i_image = GETINT16(p_buffer);
+        if( var_Get( p_input, "spu-channel", &val ) )
+        {
+          vlc_object_release( p_input );
+          return NULL;
+        }
 
-    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 );
-    }
+        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 ( i_packet != i_expected_packet ) {
-      msg_Warn( p_dec, "expecting subtitle image packet %u but found %u",
-                i_expected_packet, i_packet);
+        if( val.i_int == -1 || val.i_int != p_buffer[0] )
+          return NULL;
     }
 
-    p_sys->i_packet = i_packet;
 
-    if ( p_sys->i_packet == 0 ) {
+    /* 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, p_block->i_buffer - 5 );
+    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->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 );
-
+    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;
 }