* ogt.c : Overlay Graphics Text (SVCD subtitles) decoder thread
*****************************************************************************
* Copyright (C) 2003 VideoLAN
- * $Id: ogt.c,v 1.3 2003/12/22 02:24:51 sam Exp $
+ * $Id: ogt.c,v 1.4 2003/12/26 02:47:59 rocky Exp $
*
* Authors: Rocky Bernstein
* based on code from:
/*****************************************************************************
* Local prototypes
*****************************************************************************/
+static void InitSubtitleBlock( decoder_sys_t * p_sys );
static vout_thread_t *FindVout( decoder_t *);
static block_t *Reassemble( decoder_t *, block_t ** );
static block_t *Packetize( decoder_t *, block_t ** );
-/*****************************************************************************
- InitSubtitleBlock:
-
-Initialize so the next packet will start off a new one.
-
- *****************************************************************************/
-static void
-InitSubtitleBlock( 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;
-
-}
-
-
/*****************************************************************************
* DecoderOpen
*****************************************************************************
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->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;
InitSubtitleBlock( p_sys );
InitSubtitleBlock ( p_sys );
}
+
}
/*****************************************************************************
* Packetize:
*****************************************************************************/
-static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
+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 );
return NULL;
}
-/*
- The following information is mostly extracted from the SubMux package of
- unknown author with additional experimentation.
+/* following functions are local */
- The format is roughly as follows (everything is big-endian):
+static void
+InitSubtitleData(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;
+}
- 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
- uint16 length in bytes of the rest
- byte option flags, unknown meaning except bit 3 (0x08) indicates
- presence of the duration field
- byte unknown
- uint32 duration in 1/90000ths of a second (optional), start time
- is as indicated by the PTS in the PES header
- uint32 xpos
- uint32 ypos
- uint32 width (must be even)
- uint32 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)
- uint32 shift duration in 1/90000ths of a second
- uint16 offset of odd field (subtitle image is presented interlaced)
- byte[] bit image
-
- The image is encoded using two bits per pixel that select a palette
- entry except that value 00 starts a limited rle. When 00 is seen,
- the next two bits (00-11) encode the number of pixels (1-4, add one to
- the indicated value) to fill 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 lenght and the complete subtitle
- is padded to a 4-byte multiple that always include one zero byte at
- the end.
-*/
-
-/* FIXME: do we really need p_buffer and p?
- Can't all of thes _offset's and _lengths's get removed?
-*/
-static void
-ParseHeader( decoder_t *p_dec, uint8_t *p_buffer, block_t *p_block )
+static void
+AppendData ( decoder_t *p_dec, uint8_t *buffer, uint32_t buf_len )
{
decoder_sys_t *p_sys = p_dec->p_sys;
- uint8_t *p = p_buffer;
- int i;
-
- p_sys->i_pts = p_block->i_pts;
+ int chunk_length = buf_len;
- p_sys->i_spu_size = GETINT16(p);
- p_sys->i_options = *p++;
- p_sys->i_options2 = *p++;
+ 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 );
- if ( p_sys->i_options & 0x08 ) {
- p_sys->i_duration = GETINT32(p);
- } 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->pi_palette[i].y = *p++;
- p_sys->pi_palette[i].u = *p++;
- p_sys->pi_palette[i].v = *p++;
- /* We have just 4-bit resolution for alpha, but the value for SVCD
- * has 8 bits so we scale down the values to the acceptable range */
- p_sys->pi_palette[i].t = (*p++) >> 4;
+ chunk_length = p_sys->i_spu_size - p_sys->subtitle_data_pos;
}
- p_sys->i_cmd = *p++;
- /* We do not really know this, FIXME */
- if ( p_sys->i_cmd ) {
- p_sys->i_cmd_arg = GETINT32(p);
+
+ if ( chunk_length > 0 ) {
+ 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);
}
- /* Image starts just after skipping next short */
- p_sys->comp_image_offset = p + 2 - p_buffer;
- /* There begins the first field, so no correction needed */
- p_sys->first_field_offset = 0;
- /* Actually, this is measured against a different origin, so we have to
- adjust it */
- p_sys->second_field_offset = GETINT16(p);
- p_sys->comp_image_offset = p - p_buffer;
- p_sys->comp_image_length =
- p_sys->subtitle_data_length - p_sys->comp_image_offset;
- p_sys->metadata_length = p_sys->comp_image_offset;
-
- /*spuogt_init_subtitle_data(p_sys);*/
+}
+
+/*****************************************************************************
+ InitSubtitleBlock:
+
+Initialize so the next packet will start off a new one.
+ *****************************************************************************/
+static void
+InitSubtitleBlock( 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;
- dbg_print( (DECODE_DBG_PACKET),
- "x-start: %d, y-start: %d, width: %d, height %d, "
- "spu size: %d, duration: %u",
- p_sys->i_x_start, p_sys->i_y_start,
- p_sys->i_width, p_sys->i_height,
- p_sys->i_spu_size, p_sys->i_duration );
}
-
#define SPU_HEADER_LEN 5
/*****************************************************************************
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.
+ 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.
p_buffer = p_block->p_buffer;
- dbg_print( (DECODE_DBG_CALL|DECODE_DBG_PACKET),
- "header: 0x%02x 0x%02x 0x%02x 0x%02x\n",
- p_buffer[1], p_buffer[2], p_buffer[3], p_buffer[4] );
+ 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);
+ 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;
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\n",
+ msg_Warn( p_dec, "expecting subtitle image %u but found %u",
i_expected_image, p_sys->i_image );
}
if ( p_sys->i_packet == 0 ) {
/* First packet in the subtitle block */
- ParseHeader( p_dec, p_buffer, p_block );
+ E_(ParseHeader)( p_dec, p_buffer, p_block );
+ InitSubtitleData(p_sys);
}
+ /* FIXME - remove append_data and use chainappend */
+ AppendData( p_dec, p_buffer, p_block->i_buffer - 5 );
+
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)
return NULL;
}
-/* following functions are local */
-
/*****************************************************************************
* FindVout: Find a vout or wait for one to be created.
*****************************************************************************/
* ogt.h : Overlay Graphics Text (SVCD subtitles) decoder thread interface
*****************************************************************************
* Copyright (C) 2003 VideoLAN
- * $Id: ogt.h,v 1.3 2003/12/22 14:32:55 sam Exp $
+ * $Id: ogt.h,v 1.4 2003/12/26 02:47:59 rocky Exp $
*
* Author: Rocky Bernstein
* based on code from:
#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_INFO 8
+#define DECODE_DBG_IMAGE 8 /* image bitmaps */
+#define DECODE_DBG_INFO 16
#define DECODE_DEBUG 1
#if DECODE_DEBUG
#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;
+/* FIXME: REMOVE THE BELOW. */
/* Color and transparency of a pixel or a palette (CLUT) entry */
typedef struct ogt_yuvt_val_s {
uint8_t y;
uint8_t u;
uint8_t v;
uint8_t t;
-} ogt_yuvt_val_t;
+} ogt_yuvt_t;
-struct decoder_sys_t
-{
- int i_debug; /* debugging mask */
+/* The storage used by one pixel */
+#define PIXEL_SIZE 4
- int b_packetizer;
+/* Size in bytes of YUV portion above. */
+#define YUV_SIZE 3
- mtime_t i_pts; /* Start PTS of subtitle block */
- int i_spu_size; /* size of the allocated subtitle_data */
- 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. */
+/* Transparency plane. NOTE: see vlc_video.h for V_PLANE */
+#define T_PLANE V_PLANE+1
- 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 */
+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;
- /* Move into subpicture_sys_t? */
- uint16_t comp_image_offset; /* offset from subtitle_data to compressed
- image data */
- int comp_image_length; /* size of the compressed image data */
- int first_field_offset;
- int second_field_offset;
+ /* 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 comp_image_offset; /* offset from subtitle_data to compressed
+ image data */
+ int comp_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 */
- int subtitle_data_pos; /* where to write next chunk */
- int subtitle_data_length; /* goal for subtitle_data_pos while gathering,
- length of used subtitle_data later */
+ int subtitle_data_pos; /* where to write next chunk */
- uint32_t i_duration; /* how long to display the image, 0 stands
- for "until next subtitle" */
+ uint32_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 */
+ 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_val_t pi_palette[4];
+ ogt_yuvt_t pi_palette[NUM_SUBTITLE_COLORS];
uint8_t i_options;
uint8_t i_options2;
struct subpicture_sys_t
{
- mtime_t i_pts; /* presentation timestamp */
-
- int pi_offset[2]; /* byte offsets to data */
- void *p_data;
-
- /* Color information */
- vlc_bool_t b_palette;
- ogt_yuvt_val_t pi_palette[4];
-
-#ifndef FIXED
- uint8_t pi_alpha[4];
- uint8_t pi_yuv[4][3];
-#endif
-
- /* 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;
+ mtime_t i_pts; /* presentation timestamp */
+
+ u_int8_t *p_data; /* Image data one byte T, Y, U, V */
+
+ /* Color information */
+ vlc_bool_t b_palette;
+
+ /* 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;
};
/*****************************************************************************
* Prototypes
*****************************************************************************/
+void E_(ParseHeader)( decoder_t *, uint8_t *, block_t * );
void E_(ParsePacket)( decoder_t * );
-
void E_(RenderSPU) ( vout_thread_t *, picture_t *, const subpicture_t * );