Commit 31d966e0 authored by Sam Hocevar's avatar Sam Hocevar

  * The Gtk+ interface is now built as a Debian package as well. The Gnome
    package depends on it because of the icon and menu entry.
  * Added an intf_WarnHexDump() function to do raw hexadecimal dumps of
    memory areas. For debugging purposes or for real men, as you wish.
  * Lots of tidying in dvd_ioctl.c, a few comments added.
  * Better error handling in the subpicture decoder.
  * Tidied video_spu.c. More to come later.
  * Fixed subtitle displaying. Will soon work in overlay mode as well.
parent 4875485d
......@@ -451,7 +451,7 @@ all: vlc @ALIASES@ plugins
clean:
rm -f $(C_OBJ) $(CPP_OBJ) $(ASM_OBJ) $(STD_PLUGIN_OBJ)
rm -f plugins/*/*.o src/*/*.o lib/*.so
rm -f vlc @ALIASES@
rm -f vlc kvlc gvlc
distclean: clean
rm -f src/*/*.o plugins/*/*.o **/*~ *.log
......
......@@ -7,8 +7,8 @@ Standards-Version: 3.0.1
Package: vlc
Architecture: any
Depends: ${shlibs:Depends}, vlc-gnome
Suggests: vlc-sdl, vlc-esd
Depends: ${shlibs:Depends}, vlc-gtk
Suggests: vlc-sdl, vlc-esd, vlc-gnome
Description: the free MPEG and DVD player VideoLAN Client
VideoLAN is a free MPEG, MPEG2 and DVD software solution.
.
......@@ -17,12 +17,20 @@ Description: the free MPEG and DVD player VideoLAN Client
Package: vlc-gnome
Architecture: any
Depends: vlc (= ${Source-Version}), ${shlibs:Depends}
Depends: vlc (= ${Source-Version}), vlc-gtk (= ${Source-Version}), ${shlibs:Depends}
Description: Gnome plugin for the VideoLAN Client
VideoLAN is a free MPEG, MPEG2 and DVD software solution.
.
This plugin adds a Gnome interface to the VideoLAN Client.
Package: vlc-gtk
Architecture: any
Depends: vlc (= ${Source-Version}), ${shlibs:Depends}
Description: Gtk+ plugin for the VideoLAN Client
VideoLAN is a free MPEG, MPEG2 and DVD software solution.
.
This plugin adds a Gtk+ interface to the VideoLAN Client.
Package: vlc-esd
Architecture: any
Depends: vlc (= ${Source-Version}), ${shlibs:Depends}
......
......@@ -16,13 +16,14 @@ build-stamp:
./configure --prefix=/usr \
--mandir=\$${prefix}/share/man \
--infodir=\$${prefix}/share/info \
--enable-gnome --enable-fb --with-glide --with-ggi \
--with-sdl --enable-esd --enable-alsa --disable-ppro ; \
--enable-gnome --enable-gtk --enable-fb --with-glide \
--with-ggi --with-sdl --enable-esd --enable-alsa \
--disable-ppro ; \
else \
./configure --prefix=/usr \
--mandir=\$${prefix}/share/man \
--infodir=\$${prefix}/share/info \
--enable-gnome --enable-fb --with-ggi \
--enable-gnome --enable-gtk --enable-fb --with-ggi \
--with-sdl --enable-esd --enable-alsa; \
fi
......@@ -48,7 +49,7 @@ install: build
DESTDIR=`pwd`/debian/vlc/ $(MAKE) install prefix=/usr
# make symlinks for packages
for alias in ggi gnome glide esd sdl alsa ; do \
for alias in ggi gtk gnome glide esd sdl alsa ; do \
mkdir -p debian/vlc-$$alias/usr/share/doc/ ; \
ln -s vlc debian/vlc-$$alias/usr/share/doc/vlc-$$alias ; \
mkdir -p debian/vlc-$$alias/usr/lib/videolan/vlc/ ; \
......@@ -56,13 +57,13 @@ install: build
debian/vlc-$$alias/usr/lib/videolan/vlc/ ; \
done
mkdir -p debian/vlc-gnome/usr/bin/
mv debian/vlc/usr/bin/gvlc debian/vlc-gnome/usr/bin/
mkdir -p debian/vlc-gnome/usr/share/videolan/
mkdir -p debian/vlc-gtk/usr/bin/
mv debian/vlc/usr/bin/gvlc debian/vlc-gtk/usr/bin/
mkdir -p debian/vlc-gtk/usr/share/videolan/
mv debian/vlc/usr/share/videolan/gvlc.png \
debian/vlc-gnome/usr/share/videolan/
mkdir -p debian/vlc-gnome/usr/share/man/man1/
ln -s vlc.1.gz debian/vlc-gnome/usr/share/man/man1/gvlc.1.gz
debian/vlc-gtk/usr/share/videolan/
mkdir -p debian/vlc-gtk/usr/share/man/man1/
ln -s vlc.1.gz debian/vlc-gtk/usr/share/man/man1/gvlc.1.gz
# Build architecture-independent files here.
binary-indep: build install
......@@ -81,10 +82,10 @@ binary-arch: build install
# dh_installpam
# dh_installinit
dh_installcron
dh_installmanpages -Nvlc-gnome -Nvlc-ggi -Nvlc-glide -Nvlc-esd -Nvlc-sdl -Nvlc-alsa
dh_installmanpages -Nvlc-gnome -Nvlc-gtk -Nvlc-ggi -Nvlc-glide -Nvlc-esd -Nvlc-sdl -Nvlc-alsa
dh_installinfo
# dh_undocumented
dh_installchangelogs -Nvlc-gnome -Nvlc-ggi -Nvlc-glide -Nvlc-esd -Nvlc-sdl -Nvlc-alsa
dh_installchangelogs -Nvlc-gnome -Nvlc-gtk -Nvlc-ggi -Nvlc-glide -Nvlc-esd -Nvlc-sdl -Nvlc-alsa
dh_link
dh_strip
dh_compress
......
?package(vlc-gnome):command="/usr/bin/gvlc" hotkey="V" needs="X11" \
section="Apps/Viewers" title="Gnome VideoLAN Client" \
icon="/usr/share/videolan/gvlc.png"
?package(vlc-gtk):command="/usr/bin/gvlc" hotkey="V" needs="X11" \
section="Apps/Viewers" title="Gnome/Gtk VideoLAN Client" \
icon="/usr/share/videolan/gvlc.png"
This package was debianized by Samuel Hocevar <sam@zoy.org> on
Mon, 13 Mar 2000 02:21:45 +0100.
It was downloaded from ftp://ftp.videolan.org/pub/videolan/
It was taken from the CVS tree. See http://www.videolan.org/cvs.html
Upstream Author(s): The VideoLAN Team <videolan@videolan.org>
VideoLAN is Copyright 1996, 1997, 1998, 1999, 2000 The VideoLAN Team
VideoLAN is Copyright 1996, 1997, 1998, 1999, 2000, 2001 The VideoLAN Team
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
......
......@@ -85,3 +85,5 @@ void intf_IntfMsg ( char *psz_format, ... );
void intf_MsgImm ( char *psz_format, ... );
void intf_ErrMsgImm ( char *psz_format, ... );
void intf_WarnMsgImm ( int i_level, char *psz_format, ... );
void intf_WarnHexDump ( int i_level, void *p_data, int i_size );
/*****************************************************************************
* video_graphics.h: pictures manipulation primitives
* Includes function to compose, convert and display pictures, and also basic
* functions to copy pictures data or descriptors.
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors: Vincent Seguin <seguin@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.
*****************************************************************************/
/*****************************************************************************
* Requires:
* "config.h"
* "common.h"
* "mtime.h"
* "video.h"
*****************************************************************************/
/*****************************************************************************
* Prototypes
*****************************************************************************/
......@@ -2,7 +2,7 @@
* intf_beos.cpp: beos interface
*****************************************************************************
* Copyright (C) 1999, 2000, 2001 VideoLAN
* $Id: intf_beos.cpp,v 1.10 2001/02/20 07:49:12 sam Exp $
* $Id: intf_beos.cpp,v 1.11 2001/02/26 12:16:28 sam Exp $
*
* Authors: Jean-Marc Dressler <polux@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
......@@ -61,7 +61,7 @@ extern "C"
#include "main.h"
}
#include "beos_window.h"
#include "window.h"
/*****************************************************************************
* intf_sys_t: description and status of FB interface
......
......@@ -54,13 +54,13 @@ extern "C"
#include "video.h"
#include "video_output.h"
#include "interface.h" /* XXX maybe to remove if beos_window.h is splitted */
#include "interface.h" /* XXX maybe to remove if window.h is splitted */
#include "intf_msg.h"
#include "main.h"
}
#include "beos_window.h"
#include "window.h"
#define WIDTH 128
#define HEIGHT 64
......
/*****************************************************************************
* beos_window.h: beos window class prototype
* window.h: BeOS window class prototype
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Jean-Marc Dressler
* Authors: Jean-Marc Dressler <polux@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
......
......@@ -2,7 +2,7 @@
* dvd_ioctl.c: DVD ioctl replacement function
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: dvd_ioctl.c,v 1.1 2001/02/20 07:49:12 sam Exp $
* $Id: dvd_ioctl.c,v 1.2 2001/02/26 12:16:28 sam Exp $
*
* Authors: Markus Kuespert <ltlBeBoy@beosmail.com>
* Samuel Hocevar <sam@zoy.org>
......@@ -48,24 +48,23 @@
#include "dvd_ioctl.h"
/*****************************************************************************
* Local prototypes
* Local prototypes - BeOS specific
*****************************************************************************/
#if defined( SYS_BEOS )
static int dvd_do_auth ( int i_fd, dvd_authinfo *p_authinfo );
static int dvd_read_struct ( int i_fd, dvd_struct *p_dvd );
static int dvd_read_physical ( int i_fd, dvd_struct *p_dvd );
static int dvd_read_copyright ( int i_fd, dvd_struct *p_dvd );
static int dvd_read_disckey ( int i_fd, dvd_struct *p_dvd );
static int dvd_read_bca ( int i_fd, dvd_struct *p_dvd );
static int dvd_read_manufact ( int i_fd, dvd_struct *p_dvd );
static int communicate_with_dvd ( int i_fd,
struct cdrom_generic_command *p_cgc );
static void init_cdrom_command ( struct cdrom_generic_command *p_cgc,
static int ReadData ( int i_fd, dvd_struct *p_dvd );
static int ReadCopyright ( int i_fd, dvd_struct *p_dvd );
static int ReadKey ( int i_fd, dvd_struct *p_dvd );
static int ReadBCA ( int i_fd, dvd_struct *p_dvd );
static int ReadManufacturer ( int i_fd, dvd_struct *p_dvd );
static void InitGenericCommand( struct cdrom_generic_command *p_cgc,
void *buf, int i_len, int i_type );
static void setup_report_key ( struct cdrom_generic_command *p_cgc,
static void InitReadCommand ( struct cdrom_generic_command *p_cgc,
unsigned i_agid, unsigned i_type );
static void setup_send_key ( struct cdrom_generic_command *p_cgc,
static void InitWriteCommand ( struct cdrom_generic_command *p_cgc,
unsigned i_agid, unsigned i_type );
static int SendCommand ( int i_fd, struct cdrom_generic_command *p_cgc );
#endif
/*****************************************************************************
......@@ -80,285 +79,157 @@ int dvd_ioctl( int i_fd, unsigned long i_op, void *p_arg )
return( ioctl( i_fd, i_op, p_arg ) );
#elif defined( SYS_BEOS )
switch ( i_op )
{
case DVD_AUTH:
return dvd_do_auth( i_fd, (dvd_authinfo *)p_arg );
case DVD_READ_STRUCT:
return dvd_read_struct( i_fd, (dvd_struct *)p_arg );
default:
intf_ErrMsg( "css error: unknown command 0x%x", i_op );
return -1;
}
#else
return -1;
#endif
}
int i_ret;
unsigned char buf[20];
#if defined( SYS_BEOS )
struct cdrom_generic_command p_cgc;
/*****************************************************************************
* setup_report_key
*****************************************************************************/
static void setup_report_key( struct cdrom_generic_command *p_cgc,
unsigned i_agid, unsigned i_type )
{
p_cgc->cmd[0] = GPCMD_REPORT_KEY;
p_cgc->cmd[10] = i_type | (i_agid << 6);
dvd_struct *p_dvd = (dvd_struct *)p_arg;
dvd_authinfo *p_authinfo = (dvd_authinfo *)p_arg;
switch( i_type )
switch ( i_op )
{
case 0:
case 8:
case 5:
p_cgc->buflen = 8;
break;
case 1:
p_cgc->buflen = 16;
break;
case 2:
case 4:
p_cgc->buflen = 12;
break;
}
p_cgc->cmd[9] = p_cgc->buflen;
p_cgc->data_direction = CGC_DATA_READ;
}
/*****************************************************************************
* setup_send_key
*****************************************************************************/
static void setup_send_key( struct cdrom_generic_command *p_cgc,
unsigned i_agid, unsigned i_type )
{
p_cgc->cmd[0] = GPCMD_SEND_KEY;
p_cgc->cmd[10] = i_type | (i_agid << 6);
switch( i_type )
case DVD_AUTH: /* Request type is "authentication" */
{
case 1:
p_cgc->buflen = 16;
break;
case 3:
p_cgc->buflen = 12;
break;
memset( buf, 0, sizeof( buf ) );
InitGenericCommand( &p_cgc, buf, 0, CGC_DATA_READ );
case 6:
p_cgc->buflen = 8;
break;
}
p_cgc->cmd[9] = p_cgc->buflen;
p_cgc->data_direction = CGC_DATA_WRITE;
}
/*****************************************************************************
* init_cdrom_command
*****************************************************************************/
static void init_cdrom_command( struct cdrom_generic_command *p_cgc,
void *buf, int i_len, int i_type )
{
memset( p_cgc, 0, sizeof(struct cdrom_generic_command) );
if (buf)
switch( p_authinfo->type )
{
memset( buf, 0, i_len );
}
p_cgc->buffer = (char *) buf;
p_cgc->buflen = i_len;
p_cgc->data_direction = i_type;
p_cgc->timeout = 255;
}
/* DVD handling */
/*****************************************************************************
* dvd_do_auth
*****************************************************************************/
static int dvd_do_auth( int i_fd, dvd_authinfo *p_authinfo )
{
int i_ret;
unsigned char buf[20];
struct cdrom_generic_command p_cgc;
#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key))
#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge))
#if 0
struct rpc_state_t rpc_state;
#endif
case DVD_LU_SEND_AGID: /* LU data send */
memset( buf, 0, sizeof(buf) );
init_cdrom_command( &p_cgc, buf, 0, CGC_DATA_READ );
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_AGID" );
switch (p_authinfo->type)
{
/* LU data send */
case DVD_LU_SEND_AGID:
InitReadCommand( &p_cgc, p_authinfo->lsa.agid, 0 );
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_AGID" );
i_ret = SendCommand( i_fd, &p_cgc );
setup_report_key(&p_cgc, p_authinfo->lsa.agid, 0);
p_authinfo->lsa.agid = buf[7] >> 6;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
{
return i_ret;
}
p_authinfo->lsa.agid = buf[7] >> 6;
/* Returning data, let host change state */
case DVD_LU_SEND_KEY1:
break;
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_KEY1" );
case DVD_LU_SEND_KEY1:
InitReadCommand( &p_cgc, p_authinfo->lsk.agid, 2 );
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_KEY1" );
i_ret = SendCommand( i_fd, &p_cgc );
setup_report_key(&p_cgc, p_authinfo->lsk.agid, 2);
/* Copy the key */
memcpy( p_authinfo->lsk.key, &buf[4], sizeof(dvd_key) );
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
{
return i_ret;
}
copy_key(p_authinfo->lsk.key, &buf[4]);
/* Returning data, let host change state */
case DVD_LU_SEND_CHALLENGE:
break;
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_CHALLENGE" );
case DVD_LU_SEND_CHALLENGE:
InitReadCommand( &p_cgc, p_authinfo->lsc.agid, 1 );
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_CHALLENGE" );
i_ret = SendCommand( i_fd, &p_cgc );
setup_report_key(&p_cgc, p_authinfo->lsc.agid, 1);
/* Copy the challenge */
memcpy( p_authinfo->lsc.chal, &buf[4],
sizeof(dvd_challenge) );
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
{
return i_ret;
}
copy_chal(p_authinfo->lsc.chal, &buf[4]);
/* Returning data, let host change state */
break;
case DVD_LU_SEND_TITLE_KEY: /* Post-auth key */
/* Post-auth key */
case DVD_LU_SEND_TITLE_KEY:
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_TITLE_KEY" );
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_TITLE_KEY" );
InitReadCommand( &p_cgc, p_authinfo->lstk.agid, 4 );
setup_report_key(&p_cgc, p_authinfo->lstk.agid, 4);
p_cgc.cmd[5] = p_authinfo->lstk.lba;
p_cgc.cmd[4] = p_authinfo->lstk.lba >> 8;
p_cgc.cmd[3] = p_authinfo->lstk.lba >> 16;
p_cgc.cmd[2] = p_authinfo->lstk.lba >> 24;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
{
return i_ret;
}
i_ret = SendCommand( i_fd, &p_cgc );
p_authinfo->lstk.cpm = (buf[4] >> 7) & 1;
p_authinfo->lstk.cp_sec = (buf[4] >> 6) & 1;
p_authinfo->lstk.cgms = (buf[4] >> 4) & 3;
copy_key(p_authinfo->lstk.title_key, &buf[5]);
/* Returning data, let host change state */
break;
/* Copy the key */
memcpy( p_authinfo->lstk.title_key, &buf[5],
sizeof(dvd_key) );
return i_ret;
case DVD_LU_SEND_ASF:
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_ASF" );
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_ASF" );
setup_report_key(&p_cgc, p_authinfo->lsasf.agid, 5);
InitReadCommand( &p_cgc, p_authinfo->lsasf.agid, 5 );
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
{
return i_ret;
}
i_ret = SendCommand( i_fd, &p_cgc );
p_authinfo->lsasf.asf = buf[7] & 1;
break;
return i_ret;
/* LU data receive (LU changes state) */
case DVD_HOST_SEND_CHALLENGE:
case DVD_HOST_SEND_CHALLENGE: /* LU data receive */
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_CHALLENGE" );
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_CHALLENGE" );
setup_send_key(&p_cgc, p_authinfo->hsc.agid, 1);
InitWriteCommand( &p_cgc, p_authinfo->hsc.agid, 1 );
buf[1] = 0xe;
copy_chal(&buf[4], p_authinfo->hsc.chal);
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
/* Copy the challenge */
memcpy( &buf[4], p_authinfo->hsc.chal,
sizeof(dvd_challenge) );
if( (i_ret = SendCommand(i_fd, &p_cgc)) )
{
return i_ret;
}
p_authinfo->type = DVD_LU_SEND_KEY1;
break;
return 0;
case DVD_HOST_SEND_KEY2:
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_KEY2" );
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_KEY2" );
setup_send_key(&p_cgc, p_authinfo->hsk.agid, 3);
InitWriteCommand( &p_cgc, p_authinfo->hsk.agid, 3 );
buf[1] = 0xa;
copy_key(&buf[4], p_authinfo->hsk.key);
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
/* Copy the key */
memcpy( &buf[4], p_authinfo->hsk.key, sizeof(dvd_key) );
if( (i_ret = SendCommand(i_fd, &p_cgc)) )
{
p_authinfo->type = DVD_AUTH_FAILURE;
return i_ret;
}
p_authinfo->type = DVD_AUTH_ESTABLISHED;
break;
p_authinfo->type = DVD_AUTH_ESTABLISHED;
/* Misc */
case DVD_INVALIDATE_AGID:
return 0;
intf_WarnMsg( 2, "css dvd_do_auth: DVD_INVALIDATE_AGID" );
case DVD_INVALIDATE_AGID: /* Misc */
setup_report_key(&p_cgc, p_authinfo->lsa.agid, 0x3f);
intf_WarnMsg( 2, "css DoAuth: DVD_INVALIDATE_AGID" );
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
{
return i_ret;
}
InitReadCommand( &p_cgc, p_authinfo->lsa.agid, 0x3f );
break;
return SendCommand( i_fd, &p_cgc );
/* Get region settings */
case DVD_LU_SEND_RPC_STATE:
case DVD_LU_SEND_RPC_STATE: /* Get region settings */
intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_RPC_STATE "
intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_RPC_STATE "
"(unimplemented)" );
#if 0
p_dvdetup_report_key(&p_cgc, 0, 8);
memset(&rpc_state, 0, sizeof(rpc_state_t));
#if 0
p_dvdetup_report_key( &p_cgc, 0, 8 );
memset( &rpc_state, 0, sizeof(rpc_state_t) );
p_cgc.buffer = (char *) &rpc_state;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
if( (i_ret = SendCommand(i_fd, &p_cgc)) )
{
return i_ret;
}
......@@ -368,94 +239,102 @@ static int dvd_do_auth( int i_fd, dvd_authinfo *p_authinfo )
p_authinfo->lrpcs.ucca = rpc_state.ucca;
p_authinfo->lrpcs.region_mask = rpc_state.region_mask;
p_authinfo->lrpcs.rpc_scheme = rpc_state.rpc_scheme;
#endif
#endif
break;
return 0;
/* Set region settings */
case DVD_HOST_SEND_RPC_STATE:
case DVD_HOST_SEND_RPC_STATE: /* Set region settings */
intf_WarnMsg( 2, "css dvd_do_auth: DVD_HOST_SEND_RPC_STATE" );
intf_WarnMsg( 2, "css DoAuth: DVD_HOST_SEND_RPC_STATE" );
setup_send_key(&p_cgc, 0, 6);
InitWriteCommand( &p_cgc, 0, 6 );
buf[1] = 6;
buf[4] = p_authinfo->hrpcs.pdrc;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &p_cgc)))
{
return i_ret;
}
break;
return SendCommand( i_fd, &p_cgc );
default:
intf_ErrMsg( "css dvd_do_auth: invalid DVD key ioctl" );
intf_ErrMsg( "css DoAuth: invalid DVD key ioctl" );
return -1;
}
}
return 0;
}
/*****************************************************************************
* dvd_read_struct
*****************************************************************************/
static int dvd_read_struct( int i_fd, dvd_struct *p_dvd )
{
switch (p_dvd->type)
case DVD_READ_STRUCT: /* Request type is "read structure" */
{
switch( p_dvd->type )
{
case DVD_STRUCT_PHYSICAL:
intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_PHYSICAL" );
return dvd_read_physical(i_fd, p_dvd);
intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_PHYSICAL" );
return ReadData( i_fd, p_dvd );
case DVD_STRUCT_COPYRIGHT:
intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_COPYRIGHT" );
return dvd_read_copyright(i_fd, p_dvd);
intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_COPYRIGHT" );
return ReadCopyright( i_fd, p_dvd );
case DVD_STRUCT_DISCKEY:
intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_DISCKEY" );
return dvd_read_disckey(i_fd, p_dvd);
intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_DISCKEY" );
return ReadKey( i_fd, p_dvd );
case DVD_STRUCT_BCA:
intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_BCA" );
return dvd_read_bca(i_fd, p_dvd);
intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_BCA" );
return ReadBCA( i_fd, p_dvd );
case DVD_STRUCT_MANUFACT:
intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_MANUFACT" );
return dvd_read_manufact(i_fd, p_dvd);
intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_MANUFACT" );
return ReadManufacturer( i_fd, p_dvd );
default:
intf_WarnMsg( 2, "css dvd_read_struct: invalid request (%d)",
intf_WarnMsg( 2, "css ReadStruct: invalid request (%d)",
p_dvd->type );
return -1;
}
}
default: /* Unknown request type */
{
intf_ErrMsg( "css error: unknown command 0x%x", i_op );
return -1;
}
}
#else
return -1;
#endif
}
/* Local prototypes */
#if defined( SYS_BEOS )
/*****************************************************************************
* dvd_read_physical
* ReadData: Get data structure information from the DVD.
*****************************************************************************/
static int dvd_read_physical( int i_fd, dvd_struct *p_dvd )
static int ReadData( int i_fd, dvd_struct *p_dvd )
{
int i_ret, i;
u_char buf[4 + 4 * 20], *base;
struct dvd_layer *layer;
struct cdrom_generic_command cgc;
init_cdrom_command( &cgc, buf, sizeof(buf), CGC_DATA_READ );
InitGenericCommand( &cgc, buf, sizeof(buf), CGC_DATA_READ );
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[6] = p_dvd->physical.layer_num;
cgc.cmd[7] = p_dvd->type;
cgc.cmd[9] = cgc.buflen & 0xff;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &cgc)))
if( (i_ret = SendCommand(i_fd, &cgc)) )
{
return i_ret;
}
......@@ -488,15 +367,15 @@ static int dvd_read_physical( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_copyright
* ReadCopyright: get copyright information from the DVD.
*****************************************************************************/
static int dvd_read_copyright( int i_fd, dvd_struct *p_dvd )
static int ReadCopyright( int i_fd, dvd_struct *p_dvd )
{
int i_ret;
u_char buf[8];
struct cdrom_generic_command cgc;
init_cdrom_command( &cgc, buf, sizeof(buf), CGC_DATA_READ );
InitGenericCommand( &cgc, buf, sizeof(buf), CGC_DATA_READ );
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[6] = p_dvd->copyright.layer_num;
......@@ -504,8 +383,7 @@ static int dvd_read_copyright( int i_fd, dvd_struct *p_dvd )
cgc.cmd[8] = cgc.buflen >> 8;
cgc.cmd[9] = cgc.buflen & 0xff;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if( (i_ret = communicate_with_dvd(i_fd, &cgc)) )
if( (i_ret = SendCommand(i_fd, &cgc)) )
{
return i_ret;
}
......@@ -517,9 +395,9 @@ static int dvd_read_copyright( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_disckey
* ReadKey: get a key from the DVD.
*****************************************************************************/
static int dvd_read_disckey( int i_fd, dvd_struct *p_dvd )
static int ReadKey( int i_fd, dvd_struct *p_dvd )
{
int i_ret, size;
u_char *buf;
......@@ -533,17 +411,17 @@ static int dvd_read_disckey( int i_fd, dvd_struct *p_dvd )
return -ENOMEM;
}
#endif
buf = (u_char *) malloc(size);
buf = (u_char *) malloc( size );
InitGenericCommand( &cgc, buf, size, CGC_DATA_READ );
init_cdrom_command(&cgc, buf, size, CGC_DATA_READ);
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = p_dvd->type;
cgc.cmd[8] = size >> 8;
cgc.cmd[9] = size & 0xff;
cgc.cmd[10] = p_dvd->disckey.agid << 6;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if( !(i_ret = communicate_with_dvd(i_fd, &cgc)) )
if( !(i_ret = SendCommand(i_fd, &cgc)) )
{
memcpy( p_dvd->disckey.value, &buf[4], sizeof(p_dvd->disckey.value) );
}
......@@ -553,21 +431,24 @@ static int dvd_read_disckey( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_bca
* ReadBCA: read the Burst Cutting Area of a DVD.
*****************************************************************************
* The BCA is a special part of the DVD which is used to burn additional
* data after it has been manufactured. DIVX is an exemple.
*****************************************************************************/
static int dvd_read_bca( int i_fd, dvd_struct *p_dvd )
static int ReadBCA( int i_fd, dvd_struct *p_dvd )
{
int i_ret;
u_char buf[4 + 188];
struct cdrom_generic_command cgc;
init_cdrom_command( &cgc, buf, sizeof(buf), CGC_DATA_READ );
InitGenericCommand( &cgc, buf, sizeof(buf), CGC_DATA_READ );
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = p_dvd->type;
cgc.cmd[9] = cgc.buflen = 0xff;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if( (i_ret = communicate_with_dvd(i_fd, &cgc)) )
if( (i_ret = SendCommand(i_fd, &cgc)) )
{
return i_ret;
}
......@@ -575,7 +456,7 @@ static int dvd_read_bca( int i_fd, dvd_struct *p_dvd )
p_dvd->bca.len = buf[0] << 8 | buf[1];
if( p_dvd->bca.len < 12 || p_dvd->bca.len > 188 )
{
intf_ErrMsg("css error: invalid BCA length (%d)", p_dvd->bca.len );
intf_ErrMsg( "css error: invalid BCA length (%d)", p_dvd->bca.len );
return -1;
}
......@@ -585,15 +466,15 @@ static int dvd_read_bca( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* dvd_read_manufact
* ReadManufacturer: get manufacturer information from the DVD.
*****************************************************************************/
static int dvd_read_manufact( int i_fd, dvd_struct *p_dvd )
static int ReadManufacturer( int i_fd, dvd_struct *p_dvd )
{
int i_ret = 0, size;
u_char *buf;
struct cdrom_generic_command cgc;
size = sizeof(p_dvd->manufact.value) + 4;
size = sizeof( p_dvd->manufact.value ) + 4;
#if 0
if( (buf = (u_char *) kmalloc(size, GFP_KERNEL)) == NULL )
......@@ -603,14 +484,14 @@ static int dvd_read_manufact( int i_fd, dvd_struct *p_dvd )
#endif
buf = (u_char *) malloc(size);
init_cdrom_command( &cgc, buf, size, CGC_DATA_READ );
InitGenericCommand( &cgc, buf, size, CGC_DATA_READ );
cgc.cmd[0] = GPCMD_READ_DVD_STRUCTURE;
cgc.cmd[7] = p_dvd->type;
cgc.cmd[8] = size >> 8;
cgc.cmd[9] = size & 0xff;
/* handle uniform packets for scsi type devices (scsi,atapi) */
if ((i_ret = communicate_with_dvd(i_fd, &cgc)))
if( (i_ret = SendCommand(i_fd, &cgc)) )
{
return i_ret;
}
......@@ -618,8 +499,8 @@ static int dvd_read_manufact( int i_fd, dvd_struct *p_dvd )
p_dvd->manufact.len = buf[0] << 8 | buf[1];
if( p_dvd->manufact.len < 0 || p_dvd->manufact.len > 2048 )
{
intf_ErrMsg( "css error: invalid manufacturer info length "
"(%d)\n", p_dvd->bca.len );
intf_ErrMsg( "css error: invalid manufacturer info length (%d)",
p_dvd->bca.len );
i_ret = -1;
}
else
......@@ -632,11 +513,104 @@ static int dvd_read_manufact( int i_fd, dvd_struct *p_dvd )
}
/*****************************************************************************
* communicate_with_dvd
* InitGenericCommand: initialize a CGC structure
*****************************************************************************
* This function initializes a CDRom Generic Command structure for
* future use, either a read command or a write command.
*****************************************************************************/
static void InitGenericCommand( struct cdrom_generic_command *p_cgc,
void *buf, int i_len, int i_type )
{
memset( p_cgc, 0, sizeof( struct cdrom_generic_command ) );
if( buf != NULL )
{
memset( buf, 0, i_len );
}
p_cgc->buffer = ( char * )buf;
p_cgc->buflen = i_len;
p_cgc->data_direction = i_type;
p_cgc->timeout = 255;
}
/*****************************************************************************
* InitReadCommand: fill a CGC structure for reading purposes.
*****************************************************************************
* This function fills a CDRom Generic Command for a command which will
* read data from the DVD.
*****************************************************************************/
static void InitReadCommand( struct cdrom_generic_command *p_cgc,
unsigned i_agid, unsigned i_type )
{
p_cgc->cmd[0] = GPCMD_REPORT_KEY;
p_cgc->cmd[10] = i_type | (i_agid << 6);
/* FIXME: check what i_type means */
switch( i_type )
{
case 0:
case 8:
case 5:
p_cgc->buflen = 8;
break;
case 1:
p_cgc->buflen = 16;
break;
case 2:
case 4:
p_cgc->buflen = 12;
break;
}
p_cgc->cmd[9] = p_cgc->buflen;
p_cgc->data_direction = CGC_DATA_READ;
}
/*****************************************************************************
* InitWriteCommand: fill a CGC structure for writing purposes.
*****************************************************************************
* This function fills a CDRom Generic Command for a command which will
* send data to the DVD.
*****************************************************************************/
static int communicate_with_dvd( int i_fd,
struct cdrom_generic_command *p_cgc )
static void InitWriteCommand( struct cdrom_generic_command *p_cgc,
unsigned i_agid, unsigned i_type )
{
p_cgc->cmd[0] = GPCMD_SEND_KEY;
p_cgc->cmd[10] = i_type | (i_agid << 6);
/* FIXME: check what i_type means */
switch( i_type )
{
case 1:
p_cgc->buflen = 16;
break;
case 3:
p_cgc->buflen = 12;
break;
case 6:
p_cgc->buflen = 8;
break;
}
p_cgc->cmd[9] = p_cgc->buflen;
p_cgc->data_direction = CGC_DATA_WRITE;
}
/*****************************************************************************
* SendCommand: send a raw device command to the DVD drive.
*****************************************************************************
* This is the most important part of the ioctl emulation, the place where
* data is really sent to the DVD.
*****************************************************************************/
static int SendCommand( int i_fd, struct cdrom_generic_command *p_cgc )
{
int i;
raw_device_command rdc;
memset( &rdc, 0, sizeof( rdc ) );
......@@ -654,22 +628,14 @@ static int communicate_with_dvd( int i_fd,
}
rdc.command_length = 12;
rdc.command[0] = p_cgc->cmd[0];
rdc.command[1] = p_cgc->cmd[1];
rdc.command[2] = p_cgc->cmd[2];
rdc.command[3] = p_cgc->cmd[3];
rdc.command[4] = p_cgc->cmd[4];
rdc.command[5] = p_cgc->cmd[5];
rdc.command[6] = p_cgc->cmd[6];
rdc.command[7] = p_cgc->cmd[7];
rdc.command[8] = p_cgc->cmd[8];
rdc.command[9] = p_cgc->cmd[9];
rdc.command[10] = p_cgc->cmd[10];
rdc.command[11] = p_cgc->cmd[11];
rdc.command[12] = p_cgc->cmd[12];
/* FIXME: check if this _really_ should go up to [12] */
for( i = 0 ; i < 13 ; i++ )
{
rdc.command[i] = p_cgc->cmd[i];
}
return ioctl( i_fd, B_RAW_DEVICE_COMMAND, &rdc, sizeof(rdc) );
}
#endif
......@@ -10,7 +10,7 @@
* -dvd_udf to find files
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
* $Id: input_dvd.c,v 1.20 2001/02/22 08:59:54 stef Exp $
* $Id: input_dvd.c,v 1.21 2001/02/26 12:16:28 sam Exp $
*
* Author: Stphane Borel <stef@via.ecp.fr>
*
......@@ -711,7 +711,7 @@ static void DVDInit( input_thread_t * p_input )
/* FIXME: We consider here that one title is one title set
* it is not true !!! */
intf_WarnMsg( 2, "DVD: Number of titles: %d\n",
intf_WarnMsg( 2, "DVD: Number of titles: %d",
p_method->ifo.vmg.mat.i_tts_nb );
#define area p_input->stream.pp_areas
......
......@@ -634,8 +634,7 @@ create_intf_about (void)
GtkWidget *vbox3;
GtkWidget *label14;
GtkWidget *label18;
GtkWidget *hbox1;
GtkWidget *label15;
GtkWidget *frame1;
GtkWidget *label16;
GtkWidget *label17;
GtkWidget *dialog_action_area;
......@@ -673,40 +672,32 @@ create_intf_about (void)
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label18);
gtk_box_pack_start (GTK_BOX (vbox3), label18, FALSE, FALSE, 0);
gtk_label_set_justify (GTK_LABEL (label18), GTK_JUSTIFY_LEFT);
gtk_misc_set_padding (GTK_MISC (label18), 0, 5);
hbox1 = gtk_hbox_new (FALSE, 0);
gtk_widget_ref (hbox1);
gtk_object_set_data_full (GTK_OBJECT (intf_about), "hbox1", hbox1,
frame1 = gtk_frame_new (_("Authors"));
gtk_widget_ref (frame1);
gtk_object_set_data_full (GTK_OBJECT (intf_about), "frame1", frame1,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (hbox1);
gtk_box_pack_start (GTK_BOX (vbox3), hbox1, FALSE, FALSE, 0);
label15 = gtk_label_new (_("Authors:"));
gtk_widget_ref (label15);
gtk_object_set_data_full (GTK_OBJECT (intf_about), "label15", label15,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label15);
gtk_box_pack_start (GTK_BOX (hbox1), label15, FALSE, FALSE, 0);
gtk_label_set_justify (GTK_LABEL (label15), GTK_JUSTIFY_RIGHT);
gtk_misc_set_alignment (GTK_MISC (label15), 0.5, 1.67638e-08);
gtk_misc_set_padding (GTK_MISC (label15), 0, 10);
gtk_widget_show (frame1);
gtk_box_pack_start (GTK_BOX (vbox3), frame1, FALSE, FALSE, 0);
label16 = gtk_label_new (_("Rgis Duchesne <regis@via.ecp.fr>\nMichel Lespinasse <walken@zoy.org>\nOlivier Pomel <pomel@via.ecp.fr>\nPierre Baillet <oct@zoy.org>\nJean-Philippe Grimaldi <jeanphi@via.ecp.fr>\nAndres Krapf <dae@via.ecp.fr>\nChristophe Massiot <massiot@via.ecp.fr>\nVincent Seguin <seguin@via.ecp.fr>\nBenoit Steiner <benny@via.ecp.fr>\nArnaud de Bossoreille de Ribou <bozo@via.ecp.fr>\nJean-Marc Dressler <polux@via.ecp.fr>\nGal Hendryckx <jimmy@via.ecp.fr>\nSamuel Hocevar <sam@zoy.org>\nBrieuc Jeunhomme <bbp@via.ecp.fr>\nMichel Kaempf <maxx@via.ecp.fr>\nStphane Borel <stef@via.ecp.fr>\nRenaud Dartus <reno@via.ecp.fr>\nHenri Fallon <henri@via.ecp.fr>"));
gtk_widget_ref (label16);
gtk_object_set_data_full (GTK_OBJECT (intf_about), "label16", label16,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label16);
gtk_box_pack_start (GTK_BOX (hbox1), label16, FALSE, FALSE, 0);
gtk_container_add (GTK_CONTAINER (frame1), label16);
gtk_label_set_justify (GTK_LABEL (label16), GTK_JUSTIFY_LEFT);
gtk_misc_set_alignment (GTK_MISC (label16), 0.5, 0);
gtk_misc_set_padding (GTK_MISC (label16), 10, 10);
gtk_misc_set_padding (GTK_MISC (label16), 5, 5);
label17 = gtk_label_new (_("This is the VideoLAN client, a DVD and MPEG player. It can play MPEG and MPEG 2 files from a file or from a network source."));
gtk_widget_ref (label17);
gtk_object_set_data_full (GTK_OBJECT (intf_about), "label17", label17,
(GtkDestroyNotify) gtk_widget_unref);
gtk_widget_show (label17);
gtk_box_pack_start (GTK_BOX (vbox3), label17, FALSE, TRUE, 0);
gtk_box_pack_start (GTK_BOX (vbox3), label17, FALSE, FALSE, 0);
gtk_label_set_justify (GTK_LABEL (label17), GTK_JUSTIFY_LEFT);
gtk_label_set_line_wrap (GTK_LABEL (label17), TRUE);
gtk_misc_set_padding (GTK_MISC (label17), 0, 5);
......
......@@ -656,12 +656,12 @@
<class>GtkLabel</class>
<name>label18</name>
<label>(C) 1996, 1997, 1998, 1999, 2000, 2001 - the VideoLAN Team</label>
<justify>GTK_JUSTIFY_CENTER</justify>
<justify>GTK_JUSTIFY_LEFT</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0.5</yalign>
<xpad>0</xpad>
<ypad>0</ypad>
<ypad>5</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
......@@ -670,32 +670,16 @@
</widget>
<widget>
<class>GtkHBox</class>
<name>hbox1</name>
<homogeneous>False</homogeneous>
<spacing>0</spacing>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<widget>
<class>GtkLabel</class>
<name>label15</name>
<label>Authors:</label>
<justify>GTK_JUSTIFY_RIGHT</justify>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>1.67638e-08</yalign>
<xpad>0</xpad>
<ypad>10</ypad>
<class>GtkFrame</class>
<name>frame1</name>
<label>Authors</label>
<label_xalign>0</label_xalign>
<shadow_type>GTK_SHADOW_ETCHED_IN</shadow_type>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
</widget>
<widget>
<class>GtkLabel</class>
......@@ -722,13 +706,8 @@ Henri Fallon &lt;henri@via.ecp.fr&gt;</label>
<wrap>False</wrap>
<xalign>0.5</xalign>
<yalign>0</yalign>
<xpad>10</xpad>
<ypad>10</ypad>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>False</fill>
</child>
<xpad>5</xpad>
<ypad>5</ypad>
</widget>
</widget>
......@@ -745,7 +724,7 @@ Henri Fallon &lt;henri@via.ecp.fr&gt;</label>
<child>
<padding>0</padding>
<expand>False</expand>
<fill>True</fill>
<fill>False</fill>
</child>
</widget>
</widget>
......
......@@ -348,6 +348,43 @@ void _intf_DbgMsgImm( char *psz_file, char *psz_function, int i_line,
}
#endif
/*****************************************************************************
* intf_WarnHexDump : print a hexadecimal dump of a memory area
*****************************************************************************
* This is convenient for debugging purposes.
*****************************************************************************/
void intf_WarnHexDump( int i_level, void *p_data, int i_size )
{
int i_index = 0;
int i_subindex;
char p_string[75];
u8 *p_area = (u8 *)p_data;
intf_WarnMsg( i_level, "hexdump: dumping %i bytes at address %p",
i_size, p_data );
while( i_index < i_size )
{
i_subindex = 0;
while( ( i_subindex < 24 ) && ( i_index + i_subindex < i_size ) )
{
sprintf( p_string + 3 * i_subindex, "%.2x ",
p_area[ i_index + i_subindex ] );
i_subindex++;
}
/* -1 here is safe because we know we printed at least one */
p_string[ 3 * i_subindex - 1 ] = '\0';
intf_WarnMsg( i_level, "0x%.4x: %s", i_index, p_string );
i_index += 24;
}
intf_WarnMsg( i_level, "hexdump: %i bytes dumped", i_size );
}
/*****************************************************************************
* intf_FlushMsg (ok ?)
*****************************************************************************
......
......@@ -3,7 +3,7 @@
*****************************************************************************
* Copyright (C) 2000 VideoLAN
*
* Authors:
* Authors: Samuel 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
......@@ -34,7 +34,6 @@
#include "mtime.h"
#include "intf_msg.h"
#include "debug.h" /* ASSERT */
#include "stream_control.h"
#include "input_ext-dec.h"
......@@ -44,13 +43,18 @@
#include "spu_decoder.h"
/*
/*****************************************************************************
* Local prototypes
*/
static int InitThread ( spudec_thread_t *p_spudec );
static void RunThread ( spudec_thread_t *p_spudec );
static void ErrorThread ( spudec_thread_t *p_spudec );
static void EndThread ( spudec_thread_t *p_spudec );
*****************************************************************************/
static int InitThread ( spudec_thread_t * );
static void RunThread ( spudec_thread_t * );
static void ErrorThread ( spudec_thread_t * );
static void EndThread ( spudec_thread_t * );
static int SyncPacket ( spudec_thread_t * );
static void ParsePacket ( spudec_thread_t * );
static int ParseRLE ( spudec_thread_t *, subpicture_t * );
static int ParseControlSequences( spudec_thread_t *, subpicture_t * );
/*****************************************************************************
* spudec_CreateThread: create a spu decoder thread
......@@ -59,8 +63,6 @@ vlc_thread_t spudec_CreateThread( vdec_config_t * p_config )
{
spudec_thread_t * p_spudec;
intf_DbgMsg("spudec debug: creating spu decoder thread");
/* Allocate the memory needed to store the thread's structure */
p_spudec = (spudec_thread_t *)malloc( sizeof(spudec_thread_t) );
......@@ -84,12 +86,11 @@ vlc_thread_t spudec_CreateThread( vdec_config_t * p_config )
if ( vlc_thread_create(&p_spudec->thread_id, "spu decoder",
(vlc_thread_func_t)RunThread, (void *)p_spudec) )
{
intf_ErrMsg("spudec error: can't spawn spu decoder thread");
intf_ErrMsg( "spudec error: can't spawn spu decoder thread" );
free( p_spudec );
return( 0 );
}
intf_DbgMsg("spudec debug: spu decoder thread (%p) created", p_spudec);
return( p_spudec->thread_id );
}
......@@ -104,14 +105,11 @@ vlc_thread_t spudec_CreateThread( vdec_config_t * p_config )
*****************************************************************************/
static int InitThread( spudec_thread_t *p_spudec )
{
intf_DbgMsg("spudec debug: initializing spu decoder thread %p", p_spudec);
p_spudec->p_config->decoder_config.pf_init_bit_stream(
&p_spudec->bit_stream,
p_spudec->p_config->decoder_config.p_decoder_fifo );
/* Mark thread as running and return */
intf_DbgMsg( "spudec debug: InitThread(%p) succeeded", p_spudec );
return( 0 );
}
......@@ -123,8 +121,7 @@ static int InitThread( spudec_thread_t *p_spudec )
*****************************************************************************/
static void RunThread( spudec_thread_t *p_spudec )
{
intf_DbgMsg("spudec debug: running spu decoder thread (%p) (pid == %i)",
p_spudec, getpid());
intf_WarnMsg( 1, "spudec: spu decoder thread %i spawned", getpid() );
/*
* Initialize thread and free configuration
......@@ -137,223 +134,332 @@ static void RunThread( spudec_thread_t *p_spudec )
*/
while( (!p_spudec->p_fifo->b_die) && (!p_spudec->p_fifo->b_error) )
{
int i_packet_size;
int i_rle_size;
int i_index, i_next;
boolean_t b_valid;
subpicture_t * p_spu = NULL;
/* wait for the next SPU ID.
* XXX: We trash 0xff bytes since they probably come from
* an incomplete previous packet */
do
if( !SyncPacket( p_spudec ) )
{
i_packet_size = GetBits( &p_spudec->bit_stream, 8 );
ParsePacket( p_spudec );
}
}
while( i_packet_size == 0xff );
if( p_spudec->p_fifo->b_die )
/*
* Error loop
*/
if( p_spudec->p_fifo->b_error )
{
break;
ErrorThread( p_spudec );
}
/* End of thread */
intf_WarnMsg( 1, "spudec: destroying spu decoder thread %i", getpid() );
EndThread( p_spudec );
}
/*****************************************************************************
* ErrorThread: RunThread() error loop
*****************************************************************************
* This function is called when an error occured during thread main's loop. The
* thread can still receive feed, but must be ready to terminate as soon as
* possible.
*****************************************************************************/
static void ErrorThread( spudec_thread_t *p_spudec )
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
/* Wait until a `die' order is sent */
while( !p_spudec->p_fifo->b_die )
{
/* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY(*p_spudec->p_fifo) )
{
p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_spudec->p_fifo) );
DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait( &p_spudec->p_fifo->data_wait,
&p_spudec->p_fifo->data_lock );
}
/* We can release the lock before leaving */
vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
}
/*****************************************************************************
* EndThread: thread destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
static void EndThread( spudec_thread_t *p_spudec )
{
free( p_spudec->p_config );
free( p_spudec );
}
/*****************************************************************************
* SyncPacket: get in sync with the stream
*****************************************************************************
* This function makes a few sanity checks and returns 0 if it looks like we
* are at the beginning of a subpicture packet.
*****************************************************************************/
static int SyncPacket( spudec_thread_t *p_spudec )
{
/* Re-align the buffer on an 8-bit boundary */
RealignBits( &p_spudec->bit_stream );
/* The total SPU packet size, often bigger than a PS packet */
p_spudec->i_spu_size = GetBits( &p_spudec->bit_stream, 16 );
/* The RLE stuff size */
p_spudec->i_rle_size = GetBits( &p_spudec->bit_stream, 16 );
/* If the values we got are a bit strange, skip packet */
if( p_spudec->i_rle_size >= p_spudec->i_spu_size )
{
return( 1 );
}
/* the total size - should equal the sum of the
* PES packet size that form the SPU packet */
i_packet_size = i_packet_size << 8
| GetBits( &p_spudec->bit_stream, 8 );
return( 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.
*****************************************************************************/
static void ParsePacket( spudec_thread_t *p_spudec )
{
subpicture_t * p_spu;
/* the RLE stuff size */
i_rle_size = GetBits( &p_spudec->bit_stream, 16 );
/* Allocate the subpicture internal data. */
p_spu = vout_CreateSubPicture( p_spudec->p_vout, DVD_SUBPICTURE,
p_spudec->i_rle_size );
/* if the values we got aren't too strange, decode the data */
if( i_rle_size < i_packet_size )
if( p_spu == NULL )
{
/* allocate the subpicture.
* FIXME: we should check if the allocation failed */
p_spu = vout_CreateSubPicture( p_spudec->p_vout,
DVD_SUBPICTURE, i_rle_size );
/* get display time */
return;
}
/* Get display time */
p_spu->begin_date = p_spu->end_date
= DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts;
/* get RLE data, skip 4 bytes for the first two read offsets */
GetChunk( &p_spudec->bit_stream, p_spu->p_data,
i_rle_size - 4 );
if( ParseRLE( p_spudec, p_spu ) )
{
/* There was a parse error, delete the subpicture */
vout_DestroySubPicture( p_spudec->p_vout, p_spu );
return;
}
/* Dump the subtitle info */
intf_WarnHexDump( 0, p_spu->p_data, p_spudec->i_rle_size - 4 );
/* Getting the control part */
if( ParseControlSequences( p_spudec, p_spu ) )
{
/* There was a parse error, delete the subpicture */
vout_DestroySubPicture( p_spudec->p_vout, p_spu );
return;
}
intf_WarnMsg( 1, "spudec: got a valid %ix%i subtitle at (%i,%i), "
"RLE offsets: 0x%x 0x%x",
p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y,
p_spu->type.spu.i_offset[0], p_spu->type.spu.i_offset[1] );
/* SPU is finished - we can tell the video output to display it */
vout_DisplaySubPicture( p_spudec->p_vout, p_spu );
}
/*****************************************************************************
* ParseRLE: parse the RLE part of the subtitle
*****************************************************************************
* This part parses the subtitle graphical data and stores it in a more
* convenient structure for later decoding. For more information on the
* subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
* TODO: pre-parse the RLE stuff here.
*****************************************************************************/
static int ParseRLE( spudec_thread_t *p_spudec, subpicture_t * p_spu )
{
/* Get RLE data, skip 4 bytes for the first two read offsets */
GetChunk( &p_spudec->bit_stream, p_spu->p_data, p_spudec->i_rle_size - 4 );
if( p_spudec->p_fifo->b_die )
{
break;
return( 1 );
}
/* continue parsing after the RLE part */
i_index = i_rle_size;
return( 0 );
}
/* assume packet is valid */
b_valid = 1;
/*****************************************************************************
* ParseControlSequences: parse all SPU control sequences
*****************************************************************************
* This is the most important part in SPU decoding. We get dates, palette
* information, coordinates, and so on. For more information on the
* subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html
*****************************************************************************/
static int ParseControlSequences( spudec_thread_t *p_spudec,
subpicture_t * p_spu )
{
int i_index = p_spudec->i_rle_size;
int i_next_index = 0, i_prev_index;
int i_date;
u8 i_command;
/* getting the control part */
do
{
unsigned char i_cmd;
u16 i_date;
/* Get the sequence date */
/* Get the control sequence date */
i_date = GetBits( &p_spudec->bit_stream, 16 );
/* Next offset */
i_next = GetBits( &p_spudec->bit_stream, 16 );
i_prev_index = i_next_index;
i_next_index = GetBits( &p_spudec->bit_stream, 16 );
/* Current offset */
i_index += 4;
do
{
i_cmd = GetBits( &p_spudec->bit_stream, 8 );
i_command = GetBits( &p_spudec->bit_stream, 8 );
i_index++;
switch( i_cmd )
switch( i_command )
{
case SPU_CMD_FORCE_DISPLAY:
/* 00 (force displaying) */
break;
/* FIXME: here we have to calculate dates. It's
* around i_date * 12000 but I don't know
* how much exactly.
*/
/* FIXME: here we have to calculate dates. It's around
* i_date * 12000 but I don't know how much exactly. */
case SPU_CMD_START_DISPLAY:
/* 01 (start displaying) */
p_spu->begin_date += ( i_date * 12000 );
break;
case SPU_CMD_STOP_DISPLAY:
/* 02 (stop displaying) */
p_spu->end_date += ( i_date * 12000 );
break;
case SPU_CMD_SET_PALETTE:
/* 03xxxx (palette) - trashed */
RemoveBits( &p_spudec->bit_stream, 16 );
i_index += 2;
break;
case SPU_CMD_SET_ALPHACHANNEL:
/* 04xxxx (alpha channel) - trashed */
RemoveBits( &p_spudec->bit_stream, 16 );
i_index += 2;
break;
case SPU_CMD_SET_COORDINATES:
/* 05xxxyyyxxxyyy (coordinates) */
p_spu->i_x =
GetBits( &p_spudec->bit_stream, 12 );
p_spu->i_width = p_spu->i_x -
GetBits( &p_spudec->bit_stream, 12 ) + 1;
case SPU_CMD_SET_COORDINATES:
p_spu->i_y =
GetBits( &p_spudec->bit_stream, 12 );
/* 05xxxyyyxxxyyy (coordinates) */
p_spu->i_x = GetBits( &p_spudec->bit_stream, 12 );
p_spu->i_width = GetBits( &p_spudec->bit_stream, 12 )
- p_spu->i_x + 1;
p_spu->i_height = p_spu->i_y -
GetBits( &p_spudec->bit_stream, 12 ) + 1;
p_spu->i_y = GetBits( &p_spudec->bit_stream, 12 );
p_spu->i_height = GetBits( &p_spudec->bit_stream, 12 )
- p_spu->i_y + 1;
i_index += 6;
break;
case SPU_CMD_SET_OFFSETS:
/* 06xxxxyyyy (byte offsets) */
p_spu->type.spu.i_offset[0] =
GetBits( &p_spudec->bit_stream, 16 ) - 4;
p_spu->type.spu.i_offset[1] =
GetBits( &p_spudec->bit_stream, 16 ) - 4;
i_index += 4;
break;
case SPU_CMD_END:
/* ff (end) */
break;
default:
/* ?? (unknown command) */
intf_ErrMsg( "spudec: unknown command 0x%.2x",
i_cmd );
b_valid = 0;
break;
intf_ErrMsg( "spudec error: unknown command 0x%.2x",
i_command );
return( 1 );
}
}
while( b_valid && ( i_cmd != SPU_CMD_END ) );
}
while( b_valid && ( i_index == i_next ) );
if( b_valid )
{
/* SPU is finished - we can tell the video output
* to display it */
vout_DisplaySubPicture( p_spudec->p_vout, p_spu );
}
else
} while( i_command != SPU_CMD_END );
} while( i_index == i_next_index );
/* Check that the last index matches the previous one */
if( i_next_index != i_prev_index )
{
vout_DestroySubPicture( p_spudec->p_vout, p_spu );
intf_ErrMsg( "spudec error: index mismatch (0x%.4x != 0x%.4x)",
i_next_index, i_prev_index );
return( 1 );
}
}
else
if( i_index > p_spudec->i_spu_size )
{
/* Unexpected PES packet - trash it */
intf_ErrMsg( "spudec: trying to recover from bad packet" );
vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_spudec->p_fifo) );
DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
}
intf_ErrMsg( "spudec error: uh-oh, we went too far (0x%.4x > 0x%.4x)",
i_index, p_spudec->i_spu_size );
return( 1 );
}
/*
* Error loop
*/
if( p_spudec->p_fifo->b_error )
/* Get rid of padding bytes */
switch( p_spudec->i_spu_size - i_index )
{
ErrorThread( p_spudec );
}
case 1:
/* End of thread */
EndThread( p_spudec );
}
RemoveBits( &p_spudec->bit_stream, 8 );
i_index++;
/*****************************************************************************
* ErrorThread: RunThread() error loop
*****************************************************************************
* This function is called when an error occured during thread main's loop. The
* thread can still receive feed, but must be ready to terminate as soon as
* possible.
*****************************************************************************/
static void ErrorThread( spudec_thread_t *p_spudec )
{
/* We take the lock, because we are going to read/write the start/end
* indexes of the decoder fifo */
vlc_mutex_lock( &p_spudec->p_fifo->data_lock );
case 0:
/* Wait until a `die' order is sent */
while( !p_spudec->p_fifo->b_die )
{
/* Trash all received PES packets */
while( !DECODER_FIFO_ISEMPTY(*p_spudec->p_fifo) )
/* Zero or one padding byte, quite usual */
break;
default:
/* More than one padding byte - this is very strange, but
* we can deal with it */
intf_WarnMsg( 2, "spudec warning: %i padding bytes",
p_spudec->i_spu_size - i_index );
while( i_index < p_spudec->i_spu_size )
{
p_spudec->p_fifo->pf_delete_pes( p_spudec->p_fifo->p_packets_mgt,
DECODER_FIFO_START(*p_spudec->p_fifo) );
DECODER_FIFO_INCSTART( *p_spudec->p_fifo );
RemoveBits( &p_spudec->bit_stream, 8 );
i_index++;
}
/* Waiting for the input thread to put new PES packets in the fifo */
vlc_cond_wait( &p_spudec->p_fifo->data_wait, &p_spudec->p_fifo->data_lock );
break;
}
/* We can release the lock before leaving */
vlc_mutex_unlock( &p_spudec->p_fifo->data_lock );
}
/*****************************************************************************
* EndThread: thread destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
static void EndThread( spudec_thread_t *p_spudec )
{
intf_DbgMsg( "spudec debug: destroying spu decoder thread %p", p_spudec );
free( p_spudec->p_config );
free( p_spudec );
intf_DbgMsg( "spudec debug: spu decoder thread %p destroyed", p_spudec);
/* Successfully parsed ! */
return( 0 );
}
......@@ -3,7 +3,7 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: Samuel 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
......@@ -43,6 +43,13 @@ typedef struct spudec_thread_s
*/
vout_thread_t * p_vout; /* needed to create the spu objects */
/*
* Private properties
*/
int i_spu_size; /* size of current SPU packet */
int i_rle_size; /* size of the RLE part */
subpicture_t * p_spu;
} spudec_thread_t;
/*****************************************************************************
......
......@@ -6,7 +6,7 @@
*****************************************************************************
* Copyright (C) 2000 VideoLAN
*
* Authors:
* Authors: Vincent Seguin <seguin@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
......
/*****************************************************************************
* video_spu.h : DVD subpicture units functions
* video_spu.c : DVD subpicture units functions
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Samuel "Sam" Hocevar <sam@via.ecp.fr>
* Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
......@@ -40,272 +39,156 @@
#include "intf_msg.h"
typedef struct vout_spu_s
{
int i_id;
byte_t *p_data;
/* drawing coordinates inside the spu */
int i_x;
int i_y;
/* target size */
int i_width;
int i_height;
} vout_spu_t;
/* FIXME: fake palette - the real one has to be sought in the .IFO */
static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x8888 };
static int NewLine ( vout_spu_t *p_vspu, int *i_id );
/* i = get_nibble(); */
#define GET_NIBBLE( i ) \
if( b_aligned ) \
{ \
i_next = *p_from[i_id]; \
p_from[ i_id ]++; \
b_aligned = 0; \
i = i_next >> 4; \
} \
else \
{ \
b_aligned = 1; \
i = i_next & 0xf; \
static __inline__ u8 GetNibble( u8 *p_source, int *pi_index )
{
if( *pi_index & 0x1 )
{
return( p_source[(*pi_index)++ >> 1] & 0xf );
}
/* i = j + get_nibble(); */
#define ADD_NIBBLE( i, j ) \
if( b_aligned ) \
{ \
i_next = *p_from[i_id]; \
p_from[ i_id ]++; \
b_aligned = 0; \
i = (j) + (i_next >> 4); \
} \
else \
{ \
b_aligned = 1; \
i = (j) + (i_next & 0xf); \
else
{
return( p_source[(*pi_index)++ >> 1] >> 4 );
}
}
/*****************************************************************************
* vout_RenderSPU: draws an SPU on a picture
* vout_RenderSPU: draw an SPU on a picture
*****************************************************************************
*
*****************************************************************************/
void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_subpic,
void vout_RenderSPU( vout_buffer_t *p_buffer, subpicture_t *p_spu,
int i_bytes_per_pixel, int i_bytes_per_line )
{
int i_code = 0x00;
int i_next = 0;
int i_id = 0;
int i_color;
/* SPU size */
int i_width = p_spu->i_width;
int i_height = p_spu->i_height;
/* Drawing coordinates inside the SPU */
int i_x = 0, i_y = 0;
/* FIXME: we need a way to get this information from the stream */
#define TARGET_WIDTH 720
#define TARGET_HEIGHT 576
int i_x_scale = ( p_buffer->i_pic_width << 6 ) / TARGET_WIDTH;
int i_y_scale = ( p_buffer->i_pic_height << 6 ) / TARGET_HEIGHT;
/* FIXME: fake palette - the real one has to be sought in the .IFO */
static int p_palette[4] = { 0x0000, 0xffff, 0x5555, 0x8888 };
int i_xscale = ( p_buffer->i_pic_width << 6 ) / TARGET_WIDTH;
int i_yscale = ( p_buffer->i_pic_height << 6 ) / TARGET_HEIGHT;
boolean_t b_aligned = 1;
byte_t *p_from[2];
vout_spu_t vspu;
u8 *p_source = p_spu->p_data;
u8 *p_dest;
int pi_index[2];
p_from[1] = p_subpic->p_data + p_subpic->type.spu.i_offset[1];
p_from[0] = p_subpic->p_data + p_subpic->type.spu.i_offset[0];
pi_index[0] = ( p_spu->type.spu.i_offset[0] - 2 ) << 1;
pi_index[1] = ( p_spu->type.spu.i_offset[1] - 2 ) << 1;
vspu.i_x = 0;
vspu.i_y = 0;
vspu.i_width = TARGET_WIDTH;
vspu.i_height = TARGET_HEIGHT;
vspu.p_data = p_buffer->p_data
p_dest = p_buffer->p_data
/* add the picture coordinates and the SPU coordinates */
+ ( p_buffer->i_pic_x + ((p_subpic->i_x * i_x_scale) >> 6))
+ ( p_buffer->i_pic_x + ((p_spu->i_x * i_xscale) >> 6))
* i_bytes_per_pixel
+ ( p_buffer->i_pic_y + ((p_subpic->i_y * i_y_scale) >> 6))
+ ( p_buffer->i_pic_y + ((p_spu->i_y * i_yscale) >> 6))
* i_bytes_per_line;
/* Do we need scaling ?
* This is mostly dupliucate code except a few lines.
* This test was put out of the loop to avoid testing it
* each time.
*/
if ( i_y_scale >= (1 << 6) )
{
while( p_from[0] < (byte_t *)p_subpic->p_data
+ p_subpic->type.spu.i_offset[1] )
while( pi_index[0] >> 1 < p_spu->type.spu.i_offset[1] )
{
GET_NIBBLE( i_code );
i_code = GetNibble( p_source, pi_index + i_id );
if( i_code >= 0x04 )
{
found_code_with_scale:
found_code:
if( ((i_code >> 2) + vspu.i_x + vspu.i_y * vspu.i_width)
> vspu.i_height * vspu.i_width )
if( ((i_code >> 2) + i_x + i_y * i_width) > i_height * i_width )
{
intf_DbgMsg ( "video_spu: invalid draw request ! %d %d",
i_code >> 2, vspu.i_height * vspu.i_width
- ( (i_code >> 2) + vspu.i_x
+ vspu.i_y * vspu.i_width ) );
i_code >> 2, i_height * i_width
- ( (i_code >> 2) + i_x + i_y * i_width ) );
return;
}
else
{
if( (i_color = i_code & 0x3) )
{
u8 *p_target = &vspu.p_data[
i_bytes_per_pixel * ((vspu.i_x * i_x_scale) >> 6)
+ i_bytes_per_line * ((vspu.i_y * i_y_scale) >> 6) ];
u8 *p_target = p_dest
+ i_bytes_per_pixel * ((i_x * i_xscale) >> 6)
+ i_bytes_per_line * ((i_y * i_yscale) >> 6);
memset( p_target, p_palette[i_color],
((((i_code - 1) * i_x_scale) >> 8) + 1)
* i_bytes_per_pixel );
/* here we need some horizontal scaling (unlikely )
* we only scale up to 2x, someone watching a DVD
* with more than 2x zoom must be braindead */
p_target += i_bytes_per_line;
memset( p_target, p_palette[i_color],
((((i_code - 1) * i_x_scale) >> 8) + 1)
((((i_code >> 2) * i_xscale) >> 6) + 1)
* i_bytes_per_pixel );
}
vspu.i_x += i_code >> 2;
i_x += i_code >> 2;
}
if( vspu.i_x >= vspu.i_width )
if( i_x >= i_width )
{
/* byte-align the stream */
b_aligned = 1;
/* finish the line */
NewLine( &vspu, &i_id );
}
continue;
}
ADD_NIBBLE( i_code, (i_code << 4) );
if( i_code >= 0x10 ) /* 00 11 xx cc */
goto found_code_with_scale; /* 00 01 xx cc */
ADD_NIBBLE( i_code, (i_code << 4) );
if( i_code >= 0x040 ) /* 00 00 11 xx xx cc */
goto found_code_with_scale; /* 00 00 01 xx xx cc */
ADD_NIBBLE( i_code, (i_code << 4) );
if( i_code >= 0x0100 ) /* 00 00 00 11 xx xx xx cc */
goto found_code_with_scale; /* 00 00 00 01 xx xx xx cc */
/* if the 14 first bits are 0, then it's a newline */
if( i_code <= 0x0003 )
if( pi_index[i_id] & 0x1 )
{
if( NewLine( &vspu, &i_id ) < 0 )
return;
if( !b_aligned )
b_aligned = 1;
pi_index[i_id]++;
}
else
{
/* we have a boo boo ! */
intf_DbgMsg( "video_spu: unknown code 0x%x "
"(dest %x side %x, x=%d, y=%d)",
i_code, p_from[i_id], i_id, vspu.i_x, vspu.i_y );
if( NewLine( &vspu, &i_id ) < 0 )
return;
continue;
}
}
}
else
{
while( p_from[0] < (byte_t *)p_subpic->p_data
+ p_subpic->type.spu.i_offset[1] )
{
GET_NIBBLE( i_code );
if( i_code >= 0x04 )
{
found_code:
i_id = ~i_id & 0x1;
if( ((i_code >> 2) + vspu.i_x + vspu.i_y * vspu.i_width)
> vspu.i_height * vspu.i_width )
i_y++;
i_x = 0;
if( i_width <= i_y )
{
intf_DbgMsg ( "video_spu: invalid draw request ! %d %d",
i_code >> 2, vspu.i_height * vspu.i_width
- ( (i_code >> 2) + vspu.i_x
+ vspu.i_y * vspu.i_width ) );
return;
}
else
{
if( (i_color = i_code & 0x3) )
{
u8 *p_target = &vspu.p_data[
i_bytes_per_pixel * ((vspu.i_x * i_x_scale) >> 6)
+ i_bytes_per_line * ((vspu.i_y * i_y_scale) >> 6) ];
memset( p_target, p_palette[i_color],
((((i_code - 1) * i_x_scale) >> 8) + 1)
* i_bytes_per_pixel );
}
vspu.i_x += i_code >> 2;
}
if( vspu.i_x >= vspu.i_width )
{
/* byte-align the stream */
b_aligned = 1;
/* finish the line */
NewLine( &vspu, &i_id );
}
continue;
}
ADD_NIBBLE( i_code, (i_code << 4) );
i_code = ( i_code << 4 ) + GetNibble( p_source, pi_index + i_id );
if( i_code >= 0x10 ) /* 00 11 xx cc */
{
goto found_code; /* 00 01 xx cc */
}
ADD_NIBBLE( i_code, (i_code << 4) );
i_code = ( i_code << 4 ) + GetNibble( p_source, pi_index + i_id );
if( i_code >= 0x040 ) /* 00 00 11 xx xx cc */
{
goto found_code; /* 00 00 01 xx xx cc */
}
ADD_NIBBLE( i_code, (i_code << 4) );
i_code = ( i_code << 4 ) + GetNibble( p_source, pi_index + i_id );
if( i_code >= 0x0100 ) /* 00 00 00 11 xx xx xx cc */
goto found_code; /* 00 00 00 01 xx xx xx cc */
/* if the 14 first bits are 0, then it's a newline */
if( i_code <= 0x0003 )
{
if( NewLine( &vspu, &i_id ) < 0 )
return;
if( !b_aligned )
b_aligned = 1;
goto found_code; /* 00 00 00 01 xx xx xx cc */
}
else
if( i_code & ~0x0003 )
{
/* we have a boo boo ! */
intf_DbgMsg( "video_spu: unknown code 0x%x "
intf_ErrMsg( "video_spu: unknown code 0x%x "
"(dest %x side %x, x=%d, y=%d)",
i_code, p_from[i_id], i_id, vspu.i_x, vspu.i_y );
if( NewLine( &vspu, &i_id ) < 0 )
i_code, p_source, i_id, i_x, i_y );
return;
continue;
}
}
else
{
/* if the 14 first bits are 0, then it's a new line */
if( pi_index[i_id] & 0x1 )
{
pi_index[i_id]++;
}
}
static int NewLine( vout_spu_t *p_vspu, int *i_id )
{
*i_id = 1 - *i_id;
p_vspu->i_x = 0;
p_vspu->i_y++;
i_id = ~i_id & 0x1;
return( p_vspu->i_width - p_vspu->i_y );
i_y++;
i_x = 0;
if( i_width <= i_y )
{
return;
}
}
}
}
......@@ -3,7 +3,8 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: Samuel Hocevar <sam@zoy.org>
* Henri Fallon <henri@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
......
......@@ -3,7 +3,8 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel 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
......
......@@ -3,7 +3,8 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: Vincent Seguin <seguin@via.ecp.fr>
* Samuel 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
......
......@@ -4,7 +4,7 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: Vincent Seguin <seguin@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
......
......@@ -4,7 +4,7 @@
*****************************************************************************
* Copyright (C) 1999, 2000 VideoLAN
*
* Authors:
* Authors: Vincent Seguin <seguin@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
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment