* ./configure.in: fixed the endianness check under Solaris.
* ./src/input/input.c: strings are now initialized to "" instead of NULL.
* ./plugins/spudec/spu_decoder.c: we now properly support the subtitle
palette information we get from the DVD. Subtitles rox !
* ./src/video_output/vout_subpictures.c: removed all DVD-specific routines
and put them into spu_decoder.c.
rm -f $@ && ln -s vlc $@
.PHONY: vlc.app
-vlc.app: Makefile.opts
+vlc.app: vlc plugins
ifneq (,$(findstring darwin,$(SYS)))
rm -Rf vlc.app
cd extras/MacOSX ; pbxbuild | grep -v '^ ' | grep -v '^\t'
if ${CC-cc} conftest.c -o conftest.o >config.log 2>&1 \
&& test -f conftest.o
then
- if test `grep -l BIGenDianSyS conftest.o`
+ if test "`strings conftest.o | grep BIGenDianSyS`"
then
ac_cv_c_bigendian=yes
fi
- if test `grep -l LiTTleEnDian conftest.o`
+ if test "`strings conftest.o | grep LiTTleEnDian`"
then
ac_cv_c_bigendian=no
fi
fi
echo "$ac_t""$ac_cv_c_bigendian" 1>&6
- if test $ac_cv_c_bigendian = xunknown
+ if test x$ac_cv_c_bigendian = xunknown
then
{ echo "configure: error: Could not guess endianness, please use --with-words" 1>&2; exit 1; }
fi
"
if test x${HAVE_VLC} = x1
then
- echo "To build vlc and its plugins, type \`make vlc plugins'."
+ echo "To build vlc and its plugins, type \`make'."
fi
-if test x${HAVE_LIBDVDCSS} = x1
+if test x${NEED_LIBDVDCSS} = x1
then
echo "To build libdvdcss only, type \`make libdvdcss'."
fi
if ${CC-cc} conftest.c -o conftest.o >config.log 2>&1 \
&& test -f conftest.o
then
- if test `grep -l BIGenDianSyS conftest.o`
+ if test "`strings conftest.o | grep BIGenDianSyS`"
then
ac_cv_c_bigendian=yes
fi
- if test `grep -l LiTTleEnDian conftest.o`
+ if test "`strings conftest.o | grep LiTTleEnDian`"
then
ac_cv_c_bigendian=no
fi
fi
fi
])
- if test $ac_cv_c_bigendian = xunknown
+ if test x$ac_cv_c_bigendian = xunknown
then
AC_MSG_ERROR([Could not guess endianness, please use --with-words])
fi
"
if test x${HAVE_VLC} = x1
then
- echo "To build vlc and its plugins, type \`make vlc plugins'."
+ echo "To build vlc and its plugins, type \`make'."
fi
-if test x${HAVE_LIBDVDCSS} = x1
+if test x${NEED_LIBDVDCSS} = x1
then
echo "To build libdvdcss only, type \`make libdvdcss'."
fi
* includes all common video types and constants.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: video.h,v 1.44 2002/03/01 00:33:18 massiot Exp $
+ * $Id: video.h,v 1.45 2002/03/15 04:41:54 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
int i_width; /* picture width */
int i_height; /* picture height */
+#if 0
/* Additionnal properties depending of the subpicture type */
union
{
u32 i_border_color; /* border color */
u32 i_bg_color; /* background color */
} text;
- /* DVD subpicture units properties */
- struct
- {
- int i_offset[2]; /* byte offsets to data */
- } spu;
} type;
+#endif
+
+ /* The subpicture rendering routine */
+ void ( *pf_render ) ( const struct vout_thread_s *, picture_t *,
+ const struct subpicture_s * );
+
+ /* Private data - the subtitle plugin might want to put stuff here to
+ * keep track of the subpicture */
+ struct subpicture_sys_s *p_sys; /* subpicture data */
- /* Subpicture data, format depends of type - data can always be freely
- * modified. p_data itself (the pointer) should NEVER be modified. */
- void * p_data; /* subpicture data */
} subpicture_t;
/* Subpicture type */
#define EMPTY_SUBPICTURE 0 /* subtitle slot is empty and available */
-#define DVD_SUBPICTURE 100 /* DVD subpicture unit */
-#define TEXT_SUBPICTURE 200 /* single line text */
+#define MEMORY_SUBPICTURE 100 /* subpicture stored in memory */
/* Subpicture status */
#define FREE_SUBPICTURE 0 /* free and not allocated */
* file.c: file input (file: access plug-in)
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: file.c,v 1.1 2002/03/01 00:33:18 massiot Exp $
+ * $Id: file.c,v 1.2 2002/03/15 04:41:54 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
vlc_mutex_lock( &p_input->stream.stream_lock );
- if( p_input->psz_access != NULL
- && !strncmp( p_input->psz_access, "stream", 7 ) )
+ if( *p_input->psz_access && !strncmp( p_input->psz_access, "stream", 7 ) )
{
/* stream:%s */
p_input->stream.b_pace_control = 0;
* http.c: HTTP access plug-in
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: http.c,v 1.3 2002/03/11 07:23:09 gbazin Exp $
+ * $Id: http.c,v 1.4 2002/03/15 04:41:54 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
{
_input_socket_t * p_access_data;
char * psz_parser = p_input->psz_name;
- char * psz_server_addr = NULL;
- char * psz_server_port = NULL;
- char * psz_path = NULL;
+ char * psz_server_addr = "";
+ char * psz_server_port = "";
+ char * psz_path = "";
char * psz_proxy;
int i_server_port = 0;
return( -1 );
}
- p_access_data->psz_network = NULL;
+ p_access_data->psz_network = "";
if( config_GetIntVariable( "ipv4" ) )
{
p_access_data->psz_network = "ipv4";
{
p_access_data->psz_network = "ipv6";
}
- if( p_input->psz_access != NULL )
+ if( *p_input->psz_access )
{
/* Find out which shortcut was used */
if( !strncmp( p_input->psz_access, "http6", 5 ) )
}
/* Convert port format */
- if( psz_server_port != NULL )
+ if( *psz_server_port )
{
i_server_port = strtol( psz_server_port, &psz_parser, 10 );
if( *psz_parser )
i_server_port = 80;
}
- if( psz_server_addr == NULL )
+ if( !*psz_server_addr )
{
intf_ErrMsg( "input error: no server given" );
free( p_input->p_access_data );
* udp.c: raw UDP access plug-in
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: udp.c,v 1.3 2002/03/11 07:23:09 gbazin Exp $
+ * $Id: udp.c,v 1.4 2002/03/15 04:41:54 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
*
{
input_socket_t * p_access_data;
struct module_s * p_network;
- char * psz_network = NULL;
+ char * psz_network = "";
char * psz_parser = p_input->psz_name;
- char * psz_server_addr = NULL;
- char * psz_server_port = NULL;
- char * psz_bind_addr = NULL;
- char * psz_bind_port = NULL;
+ char * psz_server_addr = "";
+ char * psz_server_port = "";
+ char * psz_bind_addr = "";
+ char * psz_bind_port = "";
int i_bind_port = 0, i_server_port = 0;
network_socket_t socket_desc;
psz_network = "ipv6";
}
- if( p_input->psz_access != NULL )
+ if( *p_input->psz_access )
{
/* Find out which shortcut was used */
if( !strncmp( p_input->psz_access, "udp6", 5 ) )
}
/* Convert ports format */
- if( psz_server_port != NULL )
+ if( *psz_server_port )
{
i_server_port = strtol( psz_server_port, &psz_parser, 10 );
if( *psz_parser )
}
}
- if( psz_bind_port != NULL )
+ if( *psz_bind_port )
{
i_bind_port = strtol( psz_bind_port, &psz_parser, 10 );
if( *psz_parser )
* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
- * $Id: dvd_access.c,v 1.7 2002/03/15 00:57:16 stef Exp $
+ * $Id: dvd_access.c,v 1.8 2002/03/15 04:41:54 sam Exp $
*
* Author: Stéphane Borel <stef@via.ecp.fr>
*
}
else
{
- psz_raw = NULL;
+ psz_raw = "";
}
if( *psz_parser && !strtol( psz_parser, NULL, 10 ) )
{
/* we have only a partial list of options, no device */
psz_parser = psz_raw;
- psz_raw = NULL;
+ psz_raw = "";
b_options = 1;
break;
}
else
{
/* found beginning of options ; no raw device specified */
- psz_raw = NULL;
+ psz_raw = "";
b_options = 1;
}
p_dvd->i_angle = i_angle ? i_angle : 1;
}
- if( psz_raw )
+ if( *psz_raw )
{
if( *psz_raw )
{
psz_raw, strerror(errno));
/* put back '@' */
*(psz_raw - 1) = '@';
- psz_raw = NULL;
+ psz_raw = "";
}
else
{
" not a valid char device", psz_raw );
/* put back '@' */
*(psz_raw - 1) = '@';
- psz_raw = NULL;
+ psz_raw = "";
}
else
#endif
}
else
{
- psz_raw = NULL;
+ psz_raw = "";
}
}
* ipv4.c: IPv4 network abstraction layer
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: ipv4.c,v 1.5 2002/03/11 07:23:09 gbazin Exp $
+ * $Id: ipv4.c,v 1.6 2002/03/15 04:41:54 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Mathias Kretschmer <mathias@research.att.com>
memset( p_socket, 0, sizeof( struct sockaddr_in ) );
p_socket->sin_family = AF_INET; /* family */
p_socket->sin_port = htons( i_port );
- if( psz_address == NULL )
+ if( !*psz_address )
{
p_socket->sin_addr.s_addr = INADDR_ANY;
}
if (IN_MULTICAST( ntohl( inet_addr(psz_bind_addr) ) ) )
{
- psz_bind_win32 = NULL ;
+ psz_bind_win32 = "";
}
if ( BuildAddr( &sock, psz_bind_win32, i_bind_port ) == -1 )
#else
}
/* Allow broadcast reception if we bound on INADDR_ANY */
- if( psz_bind_addr == NULL )
+ if( !*psz_bind_addr )
{
i_opt = 1;
if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST,
}
}
- if( psz_server_addr != NULL )
+ if( *psz_server_addr )
{
/* Build socket for remote connection */
if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
* ipv6.c: IPv6 network abstraction layer
*****************************************************************************
* Copyright (C) 2002 VideoLAN
- * $Id: ipv6.c,v 1.2 2002/03/11 07:23:09 gbazin Exp $
+ * $Id: ipv6.c,v 1.3 2002/03/15 04:41:54 sam Exp $
*
* Authors: Alexis Guillard <alexis.guillard@bt.com>
* Christophe Massiot <massiot@via.ecp.fr>
memset( p_socket, 0, sizeof( struct sockaddr_in6 ) );
p_socket->sin6_family = AF_INET6; /* family */
p_socket->sin6_port = htons( i_port );
- if( psz_address == NULL )
+ if( !*psz_address )
{
p_socket->sin6_addr = in6addr_any;
}
}
/* Allow broadcast reception if we bound on in6addr_any */
- if( psz_bind_addr == NULL )
+ if( !*psz_bind_addr )
{
i_opt = 1;
if( setsockopt( i_handle, SOL_SOCKET, SO_BROADCAST,
/* Join the multicast group if the socket is a multicast address */
/* FIXME: To be written */
- if( psz_server_addr != NULL )
+ if( *psz_server_addr )
{
/* Build socket for remote connection */
if ( BuildAddr( &sock, psz_server_addr, i_server_port ) == -1 )
* spu_decoder.c : spu decoder thread
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
- * $Id: spu_decoder.c,v 1.11 2002/03/14 01:35:28 stef Exp $
+ * $Id: spu_decoder.c,v 1.12 2002/03/15 04:41:54 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
static void ParsePacket ( spudec_thread_t * );
static int ParseControlSequences( spudec_thread_t *, subpicture_t * );
static int ParseRLE ( spudec_thread_t *, subpicture_t *, u8 * );
+static void RenderSPU ( const vout_thread_t *, picture_t *,
+ const subpicture_t * );
/*****************************************************************************
* Capabilities
static int decoder_Run( decoder_config_t * p_config )
{
spudec_thread_t * p_spudec;
- int i;
- u32 * pi_yuv_color;
intf_WarnMsg( 3, "spudec: thread launched. Initializing ..." );
*/
p_spudec->p_fifo->b_error = InitThread( p_spudec );
- pi_yuv_color = p_config->p_demux_data;
- for( i=0 ; i<16 ; i++ )
- {
- intf_WarnMsg( 12, "spudec info: 0x%02x 0x%02x 0x%02x 0x%02x",
- *((u8*)(pi_yuv_color)),
- *((u8*)(pi_yuv_color) + 1),
- *((u8*)(pi_yuv_color) + 2),
- *((u8*)(pi_yuv_color) + 3));
- pi_yuv_color++;
- }
-
/*
* Main loop - it is not executed if an error occured during
* initialization
}
/* Allocate the subpicture internal data. */
- p_spu = vout_CreateSubPicture( p_spudec->p_vout, DVD_SUBPICTURE,
- p_spudec->i_rle_size * 4 );
+ p_spu = vout_CreateSubPicture( p_spudec->p_vout, MEMORY_SUBPICTURE,
+ sizeof( struct subpicture_sys_s )
+ + p_spudec->i_rle_size * 4 );
/* Rationale for the "p_spudec->i_rle_size * 4": we are going to
* expand the RLE stuff so that we won't need to read nibbles later
* on. This will speed things up a lot. Plus, we'll only need to do
return;
}
+ /* Fill the p_spu structure */
+ p_spu->pf_render = RenderSPU;
+ p_spu->p_sys->p_data = (void*)p_spu->p_sys
+ + sizeof( struct subpicture_sys_s );
+
/* Get display time now. If we do it later, we may miss the PTS. */
- p_spudec->i_pts = p_spudec->p_fifo->p_first->i_pts;
+ p_spu->p_sys->i_pts = p_spudec->p_fifo->p_first->i_pts;
/* Allocate the temporary buffer we will parse */
p_src = malloc( p_spudec->i_rle_size );
#if 0
/* Dump the subtitle info */
- intf_WarnHexDump( 5, p_spu->p_data, p_spudec->i_rle_size );
+ intf_WarnHexDump( 5, p_spu->p_sys->p_data, p_spudec->i_rle_size );
#endif
/* Getting the control part */
intf_WarnMsg( 3, "spudec: total size: 0x%x, RLE offsets: 0x%x 0x%x",
p_spudec->i_spu_size,
- p_spu->type.spu.i_offset[0], p_spu->type.spu.i_offset[1] );
+ p_spu->p_sys->pi_offset[0], p_spu->p_sys->pi_offset[1] );
/* SPU is finished - we can ask the video output to display it */
vout_DisplaySubPicture( p_spudec->p_vout, p_spu );
u8 i_command;
int i_date;
+ /* Dummy stuff */
+ u8 *pi_color;
+ int i;
+
/* XXX: temporary variables */
boolean_t b_force_display = 0;
case SPU_CMD_FORCE_DISPLAY:
/* 00 (force displaying) */
- p_spu->i_start = p_spudec->i_pts + ( i_date * 11000 );
+ p_spu->i_start = p_spu->p_sys->i_pts + ( i_date * 11000 );
b_force_display = 1;
break;
case SPU_CMD_START_DISPLAY:
/* 01 (start displaying) */
- p_spu->i_start = p_spudec->i_pts + ( i_date * 11000 );
+ p_spu->i_start = p_spu->p_sys->i_pts + ( i_date * 11000 );
break;
case SPU_CMD_STOP_DISPLAY:
/* 02 (stop displaying) */
- p_spu->i_stop = p_spudec->i_pts + ( i_date * 11000 );
+ p_spu->i_stop = p_spu->p_sys->i_pts + ( i_date * 11000 );
break;
case SPU_CMD_SET_PALETTE:
- /* 03xxxx (palette) - trashed */
- RemoveBits( &p_spudec->bit_stream, 16 );
+ /* 03xxxx (palette) */
+ for( i = 0; i < 4 ; i++ )
+ {
+ pi_color = (u8*)p_spudec->p_config->p_demux_data
+ + 4 * GetBits( &p_spudec->bit_stream, 4 );
+ if( p_spudec->p_config->p_demux_data )
+ {
+ p_spu->p_sys->pi_yuv[3-i][0] = pi_color[2];
+ p_spu->p_sys->pi_yuv[3-i][1] = pi_color[0];
+ p_spu->p_sys->pi_yuv[3-i][2] = pi_color[1];
+ }
+ else
+ {
+ /* No data was available from the IFO file */
+ p_spu->p_sys->pi_yuv[i][0] = 0x50 * i;
+ p_spu->p_sys->pi_yuv[i][1] = 0x80;
+ p_spu->p_sys->pi_yuv[i][2] = 0x80;
+ }
+ }
i_index += 2;
break;
case SPU_CMD_SET_ALPHACHANNEL:
- /* 04xxxx (alpha channel) - trashed */
- RemoveBits( &p_spudec->bit_stream, 16 );
+ /* 04xxxx (alpha channel) */
+ for( i = 0; i < 4 ; i++ )
+ {
+ p_spu->p_sys->pi_alpha[3-i]
+ = GetBits( &p_spudec->bit_stream, 4 );
+ }
i_index += 2;
break;
case SPU_CMD_SET_OFFSETS:
/* 06xxxxyyyy (byte offsets) */
- p_spu->type.spu.i_offset[0] =
+ p_spu->p_sys->pi_offset[0] =
GetBits( &p_spudec->bit_stream, 16 ) - 4;
- p_spu->type.spu.i_offset[1] =
+ p_spu->p_sys->pi_offset[1] =
GetBits( &p_spudec->bit_stream, 16 ) - 4;
i_index += 4;
unsigned int i_height = p_spu->i_height;
unsigned int i_x, i_y;
- u16 *p_dest = (u16 *)p_spu->p_data;
+ u16 *p_dest = (u16 *)p_spu->p_sys->p_data;
/* The subtitles are interlaced, we need two offsets */
unsigned int i_id = 0; /* Start on the even SPU layer */
unsigned int i_skipped_top = 0,
i_skipped_bottom = 0;
- pi_table[ 0 ] = p_spu->type.spu.i_offset[ 0 ] << 1;
- pi_table[ 1 ] = p_spu->type.spu.i_offset[ 1 ] << 1;
+ pi_table[ 0 ] = p_spu->p_sys->pi_offset[ 0 ] << 1;
+ pi_table[ 1 ] = p_spu->p_sys->pi_offset[ 1 ] << 1;
for( i_y = 0 ; i_y < i_height ; i_y++ )
{
return( 1 );
}
- if( i_code == (i_width << 2) ) /* FIXME: we assume 0 is transp */
+ if( (i_code >> 2) == i_width
+ && !p_spu->p_sys->pi_alpha[ i_code & 0x3 ] )
{
if( b_empty_top )
{
return( 0 );
}
+/*****************************************************************************
+ * RenderSPU: draw an SPU on a picture
+ *****************************************************************************
+ * This is a fast implementation of the subpicture drawing code. The data
+ * has been preprocessed once, so we don't need to parse the RLE buffer again
+ * and again. Most sanity checks are already done so that this routine can be
+ * as fast as possible.
+ *****************************************************************************/
+static void RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic,
+ const subpicture_t *p_spu )
+{
+ /* Common variables */
+ u16 p_clut16[4];
+ u8 *p_dest;
+ u16 *p_source = (u16 *)p_spu->p_sys->p_data;
+
+ int i_x, i_y;
+ int i_len, i_color;
+
+ /* RGB-specific */
+ int i_xscale, i_yscale, i_width, i_height, i_ytmp, i_yreal, i_ynext;
+
+ switch( p_vout->output.i_chroma )
+ {
+ /* I420 target, no scaling */
+ case FOURCC_I420:
+ case FOURCC_IYUV:
+ case FOURCC_YV12:
+
+ p_dest = p_pic->p->p_pixels + p_spu->i_x + p_spu->i_width
+ + p_vout->output.i_width * ( p_spu->i_y + p_spu->i_height );
+
+ /* Draw until we reach the bottom of the subtitle */
+ for( i_y = p_spu->i_height * p_vout->output.i_width ;
+ i_y ;
+ i_y -= p_vout->output.i_width )
+ {
+ /* Draw until we reach the end of the line */
+ for( i_x = p_spu->i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw the line */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= *p_source++ >> 2;
+ break;
+
+ case 0x0f:
+ i_len = *p_source++ >> 2;
+ memset( p_dest - i_x - i_y,
+ p_spu->p_sys->pi_yuv[i_color][0], i_len );
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = *p_source++ >> 2;
+ memset( p_dest - i_x - i_y,
+ p_spu->p_sys->pi_yuv[i_color][0], i_len );
+ i_x -= i_len;
+ break;
+ }
+ }
+ }
+
+ break;
+
+ /* RV16 target, scaling */
+ case FOURCC_RV16:
+
+ /* FIXME: get this from the DVD */
+ p_clut16[0] = 0xaaaa; p_clut16[1] = 0xffff;
+ p_clut16[2] = 0x8888; p_clut16[3] = 0x0000;
+
+ i_xscale = ( p_vout->output.i_width << 6 ) / p_vout->render.i_width;
+ i_yscale = ( p_vout->output.i_height << 6 ) / p_vout->render.i_height;
+
+ i_width = p_spu->i_width * i_xscale;
+ i_height = p_spu->i_height * i_yscale;
+
+ p_dest = p_pic->p->p_pixels + ( i_width >> 6 ) * 2
+ /* Add the picture coordinates and the SPU coordinates */
+ + ( (p_spu->i_x * i_xscale) >> 6 ) * 2
+ + ( (p_spu->i_y * i_yscale) >> 6 ) * p_vout->output.i_width * 2;
+
+ /* Draw until we reach the bottom of the subtitle */
+ for( i_y = 0 ; i_y < i_height ; )
+ {
+ i_ytmp = i_y >> 6;
+ i_y += i_yscale;
+
+ /* Check whether we need to draw one line or more than one */
+ if( i_ytmp + 1 >= ( i_y >> 6 ) )
+ {
+ /* Just one line : we precalculate i_y >> 6 */
+ i_yreal = p_vout->output.i_width * 2 * i_ytmp;
+
+ /* Draw until we reach the end of the line */
+ for( i_x = i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw the line */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= i_xscale * ( *p_source++ >> 2 );
+ break;
+
+ case 0x0f:
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_yreal,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_yreal,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ i_x -= i_len;
+ break;
+ }
+
+ }
+ }
+ else
+ {
+ i_yreal = p_vout->output.i_width * 2 * i_ytmp;
+ i_ynext = p_vout->output.i_width * 2 * i_y >> 6;
+
+ /* Draw until we reach the end of the line */
+ for( i_x = i_width ; i_x ; )
+ {
+ /* Get the RLE part, then draw as many lines as needed */
+ i_color = *p_source & 0x3;
+
+ switch( p_spu->p_sys->pi_alpha[ i_color ] )
+ {
+ case 0x00:
+ i_x -= i_xscale * ( *p_source++ >> 2 );
+ break;
+
+ case 0x0f:
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
+ i_ytmp += p_vout->output.i_width * 2 )
+ {
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ }
+ i_x -= i_len;
+ break;
+
+ default:
+ /* FIXME: we should do transparency */
+ i_len = i_xscale * ( *p_source++ >> 2 );
+ for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
+ i_ytmp += p_vout->output.i_width * 2 )
+ {
+ memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp,
+ p_clut16[ i_color ],
+ 2 * ( ( i_len >> 6 ) + 1 ) );
+ }
+ i_x -= i_len;
+ break;
+ }
+ }
+ }
+ }
+
+ break;
+
+ default:
+ intf_ErrMsg( "vout error: unknown chroma, can't render SPU" );
+ break;
+ }
+}
+
* spu_decoder.h : sub picture unit decoder thread interface
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
- * $Id: spu_decoder.h,v 1.1 2001/12/09 17:01:37 sam Exp $
+ * $Id: spu_decoder.h,v 1.2 2002/03/15 04:41:54 sam Exp $
*
* Authors: Samuel Hocevar <sam@zoy.org>
*
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
+typedef struct subpicture_sys_s
+{
+ mtime_t i_pts; /* presentation timestamp */
+
+ int pi_offset[2]; /* byte offsets to data */
+ void *p_data;
+
+ /* Color information */
+ u8 pi_alpha[4];
+ u8 pi_yuv[4][3];
+
+} subpicture_sys_t;
+
/*****************************************************************************
* spudec_thread_t : sub picture unit decoder thread descriptor
*****************************************************************************/
/*
* Private properties
*/
- mtime_t i_pts; /* presentation timestamp */
-
- // subpicture_t * p_spu;
int i_spu_size; /* size of current SPU packet */
int i_rle_size; /* size of the RLE part */
* decoders.
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
- * $Id: input.c,v 1.189 2002/03/11 07:23:09 gbazin Exp $
+ * $Id: input.c,v 1.190 2002/03/15 04:41:54 sam Exp $
*
* Authors: Christophe Massiot <massiot@via.ecp.fr>
* Alexis Guillard <alexis.guillard@bt.com>
if( !*psz_parser )
{
- p_input->psz_access = p_input->psz_demux = NULL;
+ p_input->psz_access = p_input->psz_demux = "";
p_input->psz_name = p_input->psz_source;
}
else
if( !*psz_parser )
{
/* No access */
- p_input->psz_access = NULL;
+ p_input->psz_access = "";
}
else if( *psz_parser == '/' )
{
/* No access */
- p_input->psz_access = NULL;
+ p_input->psz_access = "";
psz_parser++;
}
else
if( !*psz_parser )
{
/* No demux */
- p_input->psz_demux = NULL;
+ p_input->psz_demux = "";
}
else
{
}
}
- intf_WarnMsg( 2, "input: access=%s demux=%s name=%s",
+ intf_WarnMsg( 2, "input: access `%s', demux `%s', name `%s'",
p_input->psz_access, p_input->psz_demux,
p_input->psz_name );
* thread, and destroy a previously oppened video output thread.
*****************************************************************************
* Copyright (C) 2000-2001 VideoLAN
- * $Id: video_output.c,v 1.165 2002/03/11 07:23:10 gbazin Exp $
+ * $Id: video_output.c,v 1.166 2002/03/15 04:41:54 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
*
{
if( p_vout->p_subpicture[i_index].i_status != FREE_SUBPICTURE )
{
- free( p_vout->p_subpicture[i_index].p_data );
+ free( p_vout->p_subpicture[i_index].p_sys );
}
}
* vout_subpictures.c : subpicture management functions
*****************************************************************************
* Copyright (C) 2000 VideoLAN
- * $Id: vout_subpictures.c,v 1.10 2002/03/11 07:23:10 gbazin Exp $
+ * $Id: vout_subpictures.c,v 1.11 2002/03/15 04:41:54 sam Exp $
*
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
#include "video.h"
#include "video_output.h"
-/*****************************************************************************
- * Local prototypes
- *****************************************************************************/
-static void vout_RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic,
- const subpicture_t *p_spu );
-
/*****************************************************************************
* vout_DisplaySubPicture: display a subpicture unit
*****************************************************************************
{
/* No free subpicture or matching destroyed subpictures have been
* found, but a destroyed subpicture is still avalaible */
- free( p_destroyed_subpic->p_data );
+ free( p_destroyed_subpic->p_sys );
p_free_subpic = p_destroyed_subpic;
}
return( NULL );
}
- /* Prepare subpicture */
- switch( i_type )
- {
- case TEXT_SUBPICTURE: /* text subpicture */
- p_free_subpic->p_data = memalign( 16, i_size + 1 );
- break;
- case DVD_SUBPICTURE: /* DVD subpicture unit */
- p_free_subpic->p_data = memalign( 16, i_size );
- break;
- default:
- intf_ErrMsg( "vout error: unknown subpicture type %d", i_type );
- p_free_subpic->p_data = NULL;
- break;
- }
+ p_free_subpic->p_sys = memalign( 16, i_size );
- if( p_free_subpic->p_data != NULL )
+ if( p_free_subpic->p_sys != NULL )
{
/* Copy subpicture information, set some default values */
p_free_subpic->i_type = i_type;
/*****************************************************************************
* vout_RenderSubPictures: render a subpicture list
*****************************************************************************
- * This function renders a sub picture unit.
+ * This function renders all sub picture units in the list.
*****************************************************************************/
void vout_RenderSubPictures( vout_thread_t *p_vout, picture_t *p_pic,
subpicture_t *p_subpic )
{
-#if 0
- p_vout_font_t p_font; /* text font */
- int i_width, i_height; /* subpicture dimensions */
-#endif
-
while( p_subpic != NULL )
{
- switch( p_subpic->i_type )
- {
- case DVD_SUBPICTURE: /* DVD subpicture unit */
- vout_RenderSPU( p_vout, p_pic, p_subpic );
- break;
-
-#if 0
- case TEXT_SUBPICTURE: /* single line text */
- /* Select default font if not specified */
- p_font = p_subpic->type.text.p_font;
- if( p_font == NULL )
- {
- p_font = p_vout->p_default_font;
- }
-
- /* Compute text size (width and height fields are ignored)
- * and print it */
- vout_TextSize( p_font, p_subpic->type.text.i_style,
- p_subpic->p_data, &i_width, &i_height );
- if( !Align( p_vout, &p_subpic->i_x, &p_subpic->i_y,
- i_width, i_height, p_subpic->i_horizontal_align,
- p_subpic->i_vertical_align ) )
- {
- vout_Print( p_font,
- p_vout->p_buffer[ p_vout->i_buffer_index ].p_data +
- p_subpic->i_x * p_vout->i_bytes_per_pixel +
- p_subpic->i_y * p_vout->i_bytes_per_line,
- p_vout->i_bytes_per_pixel, p_vout->i_bytes_per_line, p_subpic->type.text.i_char_color,
- p_subpic->type.text.i_border_color,
- p_subpic->type.text.i_bg_color,
- p_subpic->type.text.i_style, p_subpic->p_data, 100 );
- SetBufferArea( p_vout, p_subpic->i_x, p_subpic->i_y,
- i_width, i_height );
- }
- break;
-#endif
-
- default:
- intf_ErrMsg( "vout error: unknown subpicture %p type %d",
- p_subpic, p_subpic->i_type );
- break;
- }
-
+ p_subpic->pf_render( p_vout, p_pic, p_subpic );
p_subpic = p_subpic->p_next;
}
}
if( p_vout->p_subpicture[i_index].i_status == READY_SUBPICTURE )
{
/* If it is a DVD subpicture, check its date */
- if( p_vout->p_subpicture[i_index].i_type == DVD_SUBPICTURE )
+ if( p_vout->p_subpicture[i_index].i_type == MEMORY_SUBPICTURE )
{
if( display_date > p_vout->p_subpicture[i_index].i_stop )
{
return p_subpic;
}
-/*****************************************************************************
- * vout_RenderSPU: draw an SPU on a picture
- *****************************************************************************
- * This is a fast implementation of the subpicture drawing code. The data
- * has been preprocessed once in spu_decoder.c, so we don't need to parse the
- * RLE buffer again and again. Most sanity checks are done in spu_decoder.c
- * so that this routine can be as fast as possible.
- *****************************************************************************/
-static void vout_RenderSPU( const vout_thread_t *p_vout, picture_t *p_pic,
- const subpicture_t *p_spu )
-{
- /* Common variables */
- u8 p_clut8[4], p_trsp[4];
- u16 p_clut16[4];
- u8 *p_dest;
- u16 *p_source = (u16 *)p_spu->p_data;
-
- int i_x, i_y;
- int i_len, i_color;
-
- /* RGB-specific */
- int i_xscale, i_yscale, i_width, i_height, i_ytmp, i_yreal, i_ynext;
-
- /* FIXME: get this from the DVD */
- p_trsp[0] = 0x00; p_trsp[1] = 0xff; p_trsp[2] = 0xff; p_trsp[3] = 0xff;
-
- switch( p_vout->output.i_chroma )
- {
- /* I420 target, no scaling */
- case FOURCC_I420:
- case FOURCC_IYUV:
- case FOURCC_YV12:
-
- /* FIXME: get this from the DVD */
- p_clut8[0] = 0xaa; p_clut8[1] = 0x44;
- p_clut8[2] = 0xff; p_clut8[3] = 0x88;
-
- p_dest = p_pic->p->p_pixels + p_spu->i_x + p_spu->i_width
- + p_vout->output.i_width * ( p_spu->i_y + p_spu->i_height );
-
- /* Draw until we reach the bottom of the subtitle */
- for( i_y = p_spu->i_height * p_vout->output.i_width ;
- i_y ;
- i_y -= p_vout->output.i_width )
- {
- /* Draw until we reach the end of the line */
- for( i_x = p_spu->i_width ; i_x ; )
- {
- /* Get the RLE part, then draw the line */
- i_color = *p_source & 0x3;
-
- switch( p_trsp[ i_color ] )
- {
- case 0x00:
- i_x -= *p_source++ >> 2;
- break;
-
- case 0xff:
- i_len = *p_source++ >> 2;
- memset( p_dest - i_x - i_y, p_clut8[ i_color ], i_len );
- i_x -= i_len;
- break;
-
- default:
- /* FIXME: we should do transparency */
- i_len = *p_source++ >> 2;
- memset( p_dest - i_x - i_y, p_clut8[ i_color ], i_len );
- i_x -= i_len;
- break;
- }
- }
- }
-
- break;
-
- /* RV16 target, scaling */
- case FOURCC_RV16:
-
- /* FIXME: get this from the DVD */
- p_clut16[0] = 0xaaaa; p_clut16[1] = 0x4444;
- p_clut16[2] = 0xffff; p_clut16[3] = 0x8888;
-
- i_xscale = ( p_vout->output.i_width << 6 ) / p_vout->render.i_width;
- i_yscale = ( p_vout->output.i_height << 6 ) / p_vout->render.i_height;
-
- i_width = p_spu->i_width * i_xscale;
- i_height = p_spu->i_height * i_yscale;
-
- p_dest = p_pic->p->p_pixels + ( i_width >> 6 ) * 2
- /* Add the picture coordinates and the SPU coordinates */
- + ( (p_spu->i_x * i_xscale) >> 6 ) * 2
- + ( (p_spu->i_y * i_yscale) >> 6 ) * p_vout->output.i_width * 2;
-
- /* Draw until we reach the bottom of the subtitle */
- for( i_y = 0 ; i_y < i_height ; )
- {
- i_ytmp = i_y >> 6;
- i_y += i_yscale;
-
- /* Check whether we need to draw one line or more than one */
- if( i_ytmp + 1 >= ( i_y >> 6 ) )
- {
- /* Just one line : we precalculate i_y >> 6 */
- i_yreal = p_vout->output.i_width * 2 * i_ytmp;
-
- /* Draw until we reach the end of the line */
- for( i_x = i_width ; i_x ; )
- {
- /* Get the RLE part, then draw the line */
- i_color = *p_source & 0x3;
-
- switch( p_trsp[ i_color ] )
- {
- case 0x00:
- i_x -= i_xscale * ( *p_source++ >> 2 );
- break;
-
- case 0xff:
- i_len = i_xscale * ( *p_source++ >> 2 );
- memset( p_dest - 2 * ( i_x >> 6 ) + i_yreal,
- p_clut16[ i_color ],
- 2 * ( ( i_len >> 6 ) + 1 ) );
- i_x -= i_len;
- break;
-
- default:
- /* FIXME: we should do transparency */
- i_len = i_xscale * ( *p_source++ >> 2 );
- memset( p_dest - 2 * ( i_x >> 6 ) + i_yreal,
- p_clut16[ i_color ],
- 2 * ( ( i_len >> 6 ) + 1 ) );
- i_x -= i_len;
- break;
- }
-
- }
- }
- else
- {
- i_yreal = p_vout->output.i_width * 2 * i_ytmp;
- i_ynext = p_vout->output.i_width * 2 * i_y >> 6;
-
- /* Draw until we reach the end of the line */
- for( i_x = i_width ; i_x ; )
- {
- /* Get the RLE part, then draw as many lines as needed */
- i_color = *p_source & 0x3;
-
- switch( p_trsp[ i_color ] )
- {
- case 0x00:
- i_x -= i_xscale * ( *p_source++ >> 2 );
- break;
-
- case 0xff:
- i_len = i_xscale * ( *p_source++ >> 2 );
- for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
- i_ytmp += p_vout->output.i_width * 2 )
- {
- memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp,
- p_clut16[ i_color ],
- 2 * ( ( i_len >> 6 ) + 1 ) );
- }
- i_x -= i_len;
- break;
-
- default:
- /* FIXME: we should do transparency */
- i_len = i_xscale * ( *p_source++ >> 2 );
- for( i_ytmp = i_yreal ; i_ytmp < i_ynext ;
- i_ytmp += p_vout->output.i_width * 2 )
- {
- memset( p_dest - 2 * ( i_x >> 6 ) + i_ytmp,
- p_clut16[ i_color ],
- 2 * ( ( i_len >> 6 ) + 1 ) );
- }
- i_x -= i_len;
- break;
- }
- }
- }
- }
-
- break;
-
- default:
- intf_ErrMsg( "vout error: unknown chroma, can't render SPU" );
- break;
- }
-}
-