From 31d966e00b3587fc620cacce8554ca95ded60529 Mon Sep 17 00:00:00 2001 From: Sam Hocevar Date: Mon, 26 Feb 2001 12:16:29 +0000 Subject: [PATCH] * 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. --- Makefile.in | 2 +- debian/control | 14 +- debian/rules | 25 +- debian/vlc-gnome.menu | 3 - debian/vlc-gtk.menu | 3 + debian/vlc.copyright | 4 +- include/intf_msg.h | 2 + include/video_graphics.h | 37 -- plugins/beos/intf_beos.cpp | 4 +- plugins/beos/vout_beos.cpp | 4 +- .../beos_window.h => plugins/beos/window.h | 5 +- plugins/dvd/dvd_ioctl.c | 628 +++++++++--------- plugins/dvd/input_dvd.c | 4 +- plugins/gtk/gtk_interface.c | 31 +- plugins/gtk/intf_gtk.glade | 41 +- src/interface/intf_msg.c | 37 ++ src/spu_decoder/spu_decoder.c | 462 ++++++++----- src/spu_decoder/spu_decoder.h | 9 +- src/video_output/video_output.c | 2 +- src/video_output/video_spu.c | 345 ++++------ src/video_output/video_spu.h | 3 +- src/video_output/video_text.c | 3 +- src/video_output/video_text.h | 3 +- src/video_output/video_yuv.c | 2 +- src/video_output/video_yuv.h | 2 +- 25 files changed, 810 insertions(+), 865 deletions(-) delete mode 100644 debian/vlc-gnome.menu create mode 100644 debian/vlc-gtk.menu delete mode 100644 include/video_graphics.h rename include/beos_window.h => plugins/beos/window.h (95%) diff --git a/Makefile.in b/Makefile.in index 855f40f11f..546fa7845f 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/debian/control b/debian/control index e52a4b56f4..81e15ebc1d 100644 --- a/debian/control +++ b/debian/control @@ -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} diff --git a/debian/rules b/debian/rules index 8b2362a1cf..4f49e92199 100755 --- a/debian/rules +++ b/debian/rules @@ -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 diff --git a/debian/vlc-gnome.menu b/debian/vlc-gnome.menu deleted file mode 100644 index e886e30aa2..0000000000 --- a/debian/vlc-gnome.menu +++ /dev/null @@ -1,3 +0,0 @@ -?package(vlc-gnome):command="/usr/bin/gvlc" hotkey="V" needs="X11" \ - section="Apps/Viewers" title="Gnome VideoLAN Client" \ - icon="/usr/share/videolan/gvlc.png" diff --git a/debian/vlc-gtk.menu b/debian/vlc-gtk.menu new file mode 100644 index 0000000000..a0c6f7cc59 --- /dev/null +++ b/debian/vlc-gtk.menu @@ -0,0 +1,3 @@ +?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" diff --git a/debian/vlc.copyright b/debian/vlc.copyright index f3d5237855..1331a58abd 100644 --- a/debian/vlc.copyright +++ b/debian/vlc.copyright @@ -1,11 +1,11 @@ This package was debianized by Samuel Hocevar 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 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 diff --git a/include/intf_msg.h b/include/intf_msg.h index 82d38e45fe..903fce5ba5 100644 --- a/include/intf_msg.h +++ b/include/intf_msg.h @@ -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 ); + diff --git a/include/video_graphics.h b/include/video_graphics.h deleted file mode 100644 index 1290584a3d..0000000000 --- a/include/video_graphics.h +++ /dev/null @@ -1,37 +0,0 @@ -/***************************************************************************** - * 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 - * - * 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 - *****************************************************************************/ - - diff --git a/plugins/beos/intf_beos.cpp b/plugins/beos/intf_beos.cpp index 1ff3d8b466..46077244ad 100644 --- a/plugins/beos/intf_beos.cpp +++ b/plugins/beos/intf_beos.cpp @@ -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 * Samuel Hocevar @@ -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 diff --git a/plugins/beos/vout_beos.cpp b/plugins/beos/vout_beos.cpp index 7ddd5d2fb4..495a44b960 100644 --- a/plugins/beos/vout_beos.cpp +++ b/plugins/beos/vout_beos.cpp @@ -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 diff --git a/include/beos_window.h b/plugins/beos/window.h similarity index 95% rename from include/beos_window.h rename to plugins/beos/window.h index e0abd47fcb..af5c6fdc63 100644 --- a/include/beos_window.h +++ b/plugins/beos/window.h @@ -1,10 +1,9 @@ /***************************************************************************** - * 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 * * 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 diff --git a/plugins/dvd/dvd_ioctl.c b/plugins/dvd/dvd_ioctl.c index 1723a2fab3..eeb9135478 100644 --- a/plugins/dvd/dvd_ioctl.c +++ b/plugins/dvd/dvd_ioctl.c @@ -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 * Samuel Hocevar @@ -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, - void *buf, int i_len, int i_type ); -static void setup_report_key ( struct cdrom_generic_command *p_cgc, - unsigned i_agid, unsigned i_type ); -static void setup_send_key ( struct cdrom_generic_command *p_cgc, - unsigned i_agid, unsigned i_type ); +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 InitReadCommand ( struct cdrom_generic_command *p_cgc, + unsigned i_agid, unsigned i_type ); +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,382 +79,262 @@ 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 + int i_ret; + unsigned char buf[20]; - return -1; -#endif -} + struct cdrom_generic_command p_cgc; -#if defined( SYS_BEOS ) + dvd_struct *p_dvd = (dvd_struct *)p_arg; + dvd_authinfo *p_authinfo = (dvd_authinfo *)p_arg; -/***************************************************************************** - * 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); - - switch( i_type ) + switch ( i_op ) { - case 0: - case 8: - case 5: - p_cgc->buflen = 8; - break; + case DVD_AUTH: /* Request type is "authentication" */ + { + memset( buf, 0, sizeof( buf ) ); + InitGenericCommand( &p_cgc, buf, 0, CGC_DATA_READ ); - case 1: - p_cgc->buflen = 16; - break; + switch( p_authinfo->type ) + { + case DVD_LU_SEND_AGID: /* LU data send */ - case 2: - case 4: - p_cgc->buflen = 12; - break; - } + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_AGID" ); - p_cgc->cmd[9] = p_cgc->buflen; - p_cgc->data_direction = CGC_DATA_READ; -} + InitReadCommand( &p_cgc, p_authinfo->lsa.agid, 0 ); -/***************************************************************************** - * 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); + i_ret = SendCommand( i_fd, &p_cgc ); - switch( i_type ) - { - case 1: - p_cgc->buflen = 16; - break; + p_authinfo->lsa.agid = buf[7] >> 6; - case 3: - p_cgc->buflen = 12; - break; + return i_ret; - case 6: - p_cgc->buflen = 8; - break; - } + case DVD_LU_SEND_KEY1: - p_cgc->cmd[9] = p_cgc->buflen; - p_cgc->data_direction = CGC_DATA_WRITE; -} + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_KEY1" ); -/***************************************************************************** - * 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) ); + InitReadCommand( &p_cgc, p_authinfo->lsk.agid, 2 ); - if (buf) - { - memset( buf, 0, i_len ); - } + i_ret = SendCommand( i_fd, &p_cgc ); - p_cgc->buffer = (char *) buf; - p_cgc->buflen = i_len; - p_cgc->data_direction = i_type; - p_cgc->timeout = 255; -} + /* Copy the key */ + memcpy( p_authinfo->lsk.key, &buf[4], sizeof(dvd_key) ); -/* DVD handling */ + return i_ret; -/***************************************************************************** - * 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; + case DVD_LU_SEND_CHALLENGE: -#define copy_key(dest,src) memcpy((dest), (src), sizeof(dvd_key)) -#define copy_chal(dest,src) memcpy((dest), (src), sizeof(dvd_challenge)) + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_CHALLENGE" ); -#if 0 - struct rpc_state_t rpc_state; -#endif + InitReadCommand( &p_cgc, p_authinfo->lsc.agid, 1 ); - memset( buf, 0, sizeof(buf) ); - init_cdrom_command( &p_cgc, buf, 0, CGC_DATA_READ ); + i_ret = SendCommand( i_fd, &p_cgc ); - switch (p_authinfo->type) - { - /* LU data send */ - case DVD_LU_SEND_AGID: + /* Copy the challenge */ + memcpy( p_authinfo->lsc.chal, &buf[4], + sizeof(dvd_challenge) ); - intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_AGID" ); + return i_ret; - setup_report_key(&p_cgc, p_authinfo->lsa.agid, 0); + case DVD_LU_SEND_TITLE_KEY: /* Post-auth key */ - /* handle uniform packets for scsi type devices (scsi,atapi) */ - if ((i_ret = communicate_with_dvd(i_fd, &p_cgc))) - { - return i_ret; - } + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_TITLE_KEY" ); - p_authinfo->lsa.agid = buf[7] >> 6; - /* Returning data, let host change state */ + InitReadCommand( &p_cgc, p_authinfo->lstk.agid, 4 ); - break; + 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; - case DVD_LU_SEND_KEY1: + i_ret = SendCommand( i_fd, &p_cgc ); - intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_KEY1" ); + 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; - setup_report_key(&p_cgc, p_authinfo->lsk.agid, 2); + /* Copy the key */ + memcpy( p_authinfo->lstk.title_key, &buf[5], + 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; - } + return i_ret; - copy_key(p_authinfo->lsk.key, &buf[4]); - /* Returning data, let host change state */ + case DVD_LU_SEND_ASF: - break; + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_ASF" ); - case DVD_LU_SEND_CHALLENGE: + InitReadCommand( &p_cgc, p_authinfo->lsasf.agid, 5 ); - 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); + p_authinfo->lsasf.asf = buf[7] & 1; - /* 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 */ + return i_ret; - break; + case DVD_HOST_SEND_CHALLENGE: /* LU data receive */ - /* Post-auth key */ - case DVD_LU_SEND_TITLE_KEY: + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_CHALLENGE" ); - intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_TITLE_KEY" ); + InitWriteCommand( &p_cgc, p_authinfo->hsc.agid, 1 ); + buf[1] = 0xe; - 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; - } - - 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 challenge */ + memcpy( &buf[4], p_authinfo->hsc.chal, + sizeof(dvd_challenge) ); - case DVD_LU_SEND_ASF: + if( (i_ret = SendCommand(i_fd, &p_cgc)) ) + { + return i_ret; + } - intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_ASF" ); + p_authinfo->type = DVD_LU_SEND_KEY1; - setup_report_key(&p_cgc, p_authinfo->lsasf.agid, 5); + return 0; - /* handle uniform packets for scsi type devices (scsi,atapi) */ - if ((i_ret = communicate_with_dvd(i_fd, &p_cgc))) - { - return i_ret; - } + case DVD_HOST_SEND_KEY2: - p_authinfo->lsasf.asf = buf[7] & 1; + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_KEY2" ); - break; + InitWriteCommand( &p_cgc, p_authinfo->hsk.agid, 3 ); + buf[1] = 0xa; - /* LU data receive (LU changes state) */ - case DVD_HOST_SEND_CHALLENGE: + /* Copy the key */ + memcpy( &buf[4], p_authinfo->hsk.key, sizeof(dvd_key) ); - intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_CHALLENGE" ); + if( (i_ret = SendCommand(i_fd, &p_cgc)) ) + { + p_authinfo->type = DVD_AUTH_FAILURE; + return i_ret; + } - setup_send_key(&p_cgc, p_authinfo->hsc.agid, 1); - buf[1] = 0xe; - copy_chal(&buf[4], p_authinfo->hsc.chal); + p_authinfo->type = DVD_AUTH_ESTABLISHED; - /* handle uniform packets for scsi type devices (scsi,atapi) */ - if ((i_ret = communicate_with_dvd(i_fd, &p_cgc))) - { - return i_ret; - } + return 0; - p_authinfo->type = DVD_LU_SEND_KEY1; + case DVD_INVALIDATE_AGID: /* Misc */ - break; + intf_WarnMsg( 2, "css DoAuth: DVD_INVALIDATE_AGID" ); - case DVD_HOST_SEND_KEY2: + InitReadCommand( &p_cgc, p_authinfo->lsa.agid, 0x3f ); - intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_KEY2" ); + return SendCommand( i_fd, &p_cgc ); - setup_send_key(&p_cgc, p_authinfo->hsk.agid, 3); - buf[1] = 0xa; - copy_key(&buf[4], p_authinfo->hsk.key); + case DVD_LU_SEND_RPC_STATE: /* Get region settings */ - /* handle uniform packets for scsi type devices (scsi,atapi) */ - if ((i_ret = communicate_with_dvd(i_fd, &p_cgc))) - { - p_authinfo->type = DVD_AUTH_FAILURE; - return i_ret; - } - p_authinfo->type = DVD_AUTH_ESTABLISHED; + intf_WarnMsg( 2, "css DoAuth: DVD_LU_SEND_RPC_STATE " + "(unimplemented)" ); - break; + #if 0 + p_dvdetup_report_key( &p_cgc, 0, 8 ); + memset( &rpc_state, 0, sizeof(rpc_state_t) ); + p_cgc.buffer = (char *) &rpc_state; - /* Misc */ - case DVD_INVALIDATE_AGID: + if( (i_ret = SendCommand(i_fd, &p_cgc)) ) + { + return i_ret; + } - intf_WarnMsg( 2, "css dvd_do_auth: DVD_INVALIDATE_AGID" ); + p_authinfo->lrpcs.type = rpc_state.type_code; + p_authinfo->lrpcs.vra = rpc_state.vra; + 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 - setup_report_key(&p_cgc, p_authinfo->lsa.agid, 0x3f); + return 0; - /* handle uniform packets for scsi type devices (scsi,atapi) */ - if ((i_ret = communicate_with_dvd(i_fd, &p_cgc))) - { - return i_ret; - } + case DVD_HOST_SEND_RPC_STATE: /* Set region settings */ - break; + intf_WarnMsg( 2, "css DoAuth: DVD_HOST_SEND_RPC_STATE" ); - /* Get region settings */ - case DVD_LU_SEND_RPC_STATE: + InitWriteCommand( &p_cgc, 0, 6 ); + buf[1] = 6; + buf[4] = p_authinfo->hrpcs.pdrc; - intf_WarnMsg( 2, "css dvd_do_auth: DVD_LU_SEND_RPC_STATE " - "(unimplemented)" ); + return SendCommand( i_fd, &p_cgc ); -#if 0 - p_dvdetup_report_key(&p_cgc, 0, 8); - memset(&rpc_state, 0, sizeof(rpc_state_t)); - p_cgc.buffer = (char *) &rpc_state; + default: + intf_ErrMsg( "css DoAuth: invalid DVD key ioctl" ); + return -1; - /* handle uniform packets for scsi type devices (scsi,atapi) */ - if ((i_ret = communicate_with_dvd(i_fd, &p_cgc))) - { - return i_ret; } + } - p_authinfo->lrpcs.type = rpc_state.type_code; - p_authinfo->lrpcs.vra = rpc_state.vra; - 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 + case DVD_READ_STRUCT: /* Request type is "read structure" */ + { + switch( p_dvd->type ) + { + case DVD_STRUCT_PHYSICAL: - break; + intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_PHYSICAL" ); - /* Set region settings */ - case DVD_HOST_SEND_RPC_STATE: + return ReadData( i_fd, p_dvd ); - intf_WarnMsg( 2, "css dvd_do_auth: DVD_HOST_SEND_RPC_STATE" ); + case DVD_STRUCT_COPYRIGHT: - setup_send_key(&p_cgc, 0, 6); - buf[1] = 6; - buf[4] = p_authinfo->hrpcs.pdrc; + intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_COPYRIGHT" ); - /* handle uniform packets for scsi type devices (scsi,atapi) */ - if ((i_ret = communicate_with_dvd(i_fd, &p_cgc))) - { - return i_ret; - } + return ReadCopyright( i_fd, p_dvd ); - break; + case DVD_STRUCT_DISCKEY: - default: - intf_ErrMsg( "css dvd_do_auth: invalid DVD key ioctl" ); - return -1; + intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_DISCKEY" ); - } + return ReadKey( i_fd, p_dvd ); - return 0; -} + case DVD_STRUCT_BCA: -/***************************************************************************** - * dvd_read_struct - *****************************************************************************/ -static int dvd_read_struct( int i_fd, dvd_struct *p_dvd ) -{ - 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); - - 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_BCA" ); - case DVD_STRUCT_DISCKEY: + return ReadBCA( i_fd, p_dvd ); - intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_DISCKEY" ); - return dvd_read_disckey(i_fd, p_dvd); + case DVD_STRUCT_MANUFACT: - case DVD_STRUCT_BCA: + intf_WarnMsg( 2, "css ReadStruct: DVD_STRUCT_MANUFACT" ); - intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_BCA" ); - return dvd_read_bca(i_fd, p_dvd); + return ReadManufacturer( i_fd, p_dvd ); - case DVD_STRUCT_MANUFACT: + default: + intf_WarnMsg( 2, "css ReadStruct: invalid request (%d)", + p_dvd->type ); - intf_WarnMsg( 2, "css dvd_read_struct: DVD_STRUCT_MANUFACT" ); - return dvd_read_manufact(i_fd, p_dvd); + return -1; + } + } - default: - intf_WarnMsg( 2, "css dvd_read_struct: invalid request (%d)", - p_dvd->type ); + 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 int communicate_with_dvd( int i_fd, - struct cdrom_generic_command *p_cgc ) +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 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 diff --git a/plugins/dvd/input_dvd.c b/plugins/dvd/input_dvd.c index 07f8fc5bcb..cc74c3aa2f 100644 --- a/plugins/dvd/input_dvd.c +++ b/plugins/dvd/input_dvd.c @@ -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: Stéphane Borel * @@ -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 diff --git a/plugins/gtk/gtk_interface.c b/plugins/gtk/gtk_interface.c index 5dd7196d6d..7376498c55 100644 --- a/plugins/gtk/gtk_interface.c +++ b/plugins/gtk/gtk_interface.c @@ -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 (_("Régis Duchesne \nMichel Lespinasse \nOlivier Pomel \nPierre Baillet \nJean-Philippe Grimaldi \nAndres Krapf \nChristophe Massiot \nVincent Seguin \nBenoit Steiner \nArnaud de Bossoreille de Ribou \nJean-Marc Dressler \nGaël Hendryckx \nSamuel Hocevar \nBrieuc Jeunhomme \nMichel Kaempf \nStéphane Borel \nRenaud Dartus \nHenri Fallon ")); 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); diff --git a/plugins/gtk/intf_gtk.glade b/plugins/gtk/intf_gtk.glade index 476b38d295..8f4205ff4c 100644 --- a/plugins/gtk/intf_gtk.glade +++ b/plugins/gtk/intf_gtk.glade @@ -656,12 +656,12 @@ GtkLabel label18 - GTK_JUSTIFY_CENTER + GTK_JUSTIFY_LEFT False 0.5 0.5 0 - 0 + 5 0 False @@ -670,33 +670,17 @@ - GtkHBox - hbox1 - False - 0 + GtkFrame + frame1 + + 0 + GTK_SHADOW_ETCHED_IN 0 False False - - GtkLabel - label15 - - GTK_JUSTIFY_RIGHT - False - 0.5 - 1.67638e-08 - 0 - 10 - - 0 - False - False - - - GtkLabel label16 @@ -722,13 +706,8 @@ Henri Fallon <henri@via.ecp.fr> False 0.5 0 - 10 - 10 - - 0 - False - False - + 5 + 5 @@ -745,7 +724,7 @@ Henri Fallon <henri@via.ecp.fr> 0 False - True + False diff --git a/src/interface/intf_msg.c b/src/interface/intf_msg.c index 68c3b6301b..c2eaec639e 100644 --- a/src/interface/intf_msg.c +++ b/src/interface/intf_msg.c @@ -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 ?) ***************************************************************************** diff --git a/src/spu_decoder/spu_decoder.c b/src/spu_decoder/spu_decoder.c index b7e7109c1b..e1a43fab34 100644 --- a/src/spu_decoder/spu_decoder.c +++ b/src/spu_decoder/spu_decoder.c @@ -3,7 +3,7 @@ ***************************************************************************** * Copyright (C) 2000 VideoLAN * - * Authors: + * Authors: Samuel Hocevar * * 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,165 +134,9 @@ 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 - { - i_packet_size = GetBits( &p_spudec->bit_stream, 8 ); - } - while( i_packet_size == 0xff ); - - if( p_spudec->p_fifo->b_die ) - { - break; - } - - /* 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 ); - - /* the RLE stuff size */ - i_rle_size = GetBits( &p_spudec->bit_stream, 16 ); - - /* if the values we got aren't too strange, decode the data */ - if( i_rle_size < i_packet_size ) - { - /* 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 */ - 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( p_spudec->p_fifo->b_die ) - { - break; - } - - /* continue parsing after the RLE part */ - i_index = i_rle_size; - - /* assume packet is valid */ - b_valid = 1; - - /* getting the control part */ - do - { - unsigned char i_cmd; - u16 i_date; - - /* Get the sequence date */ - i_date = GetBits( &p_spudec->bit_stream, 16 ); - - /* Next offset */ - i_next = GetBits( &p_spudec->bit_stream, 16 ); - - i_index += 4; - - do - { - i_cmd = GetBits( &p_spudec->bit_stream, 8 ); - i_index++; - - switch( i_cmd ) - { - 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. - */ - 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; - - p_spu->i_y = - GetBits( &p_spudec->bit_stream, 12 ); - - p_spu->i_height = p_spu->i_y - - GetBits( &p_spudec->bit_stream, 12 ) + 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; - } - } - 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 - { - vout_DestroySubPicture( p_spudec->p_vout, p_spu ); - } - } - else + if( !SyncPacket( p_spudec ) ) { - /* 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 ); + ParsePacket( p_spudec ); } } @@ -308,6 +149,7 @@ static void RunThread( spudec_thread_t *p_spudec ) } /* End of thread */ + intf_WarnMsg( 1, "spudec: destroying spu decoder thread %i", getpid() ); EndThread( p_spudec ); } @@ -336,7 +178,8 @@ static void ErrorThread( spudec_thread_t *p_spudec ) } /* 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 ); + vlc_cond_wait( &p_spudec->p_fifo->data_wait, + &p_spudec->p_fifo->data_lock ); } /* We can release the lock before leaving */ @@ -351,9 +194,272 @@ static void ErrorThread( spudec_thread_t *p_spudec ) *****************************************************************************/ 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); +} + +/***************************************************************************** + * 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 ); + } + + 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; + + /* Allocate the subpicture internal data. */ + p_spu = vout_CreateSubPicture( p_spudec->p_vout, DVD_SUBPICTURE, + p_spudec->i_rle_size ); + + if( p_spu == NULL ) + { + return; + } + + /* Get display time */ + p_spu->begin_date = p_spu->end_date + = DECODER_FIFO_START(*p_spudec->p_fifo)->i_pts; + + 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 ) + { + return( 1 ); + } + + return( 0 ); +} + + /***************************************************************************** + * 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; + + do + { + /* Get the control sequence date */ + i_date = GetBits( &p_spudec->bit_stream, 16 ); + + /* Next offset */ + i_prev_index = i_next_index; + i_next_index = GetBits( &p_spudec->bit_stream, 16 ); + + /* Current offset */ + i_index += 4; + + do + { + i_command = GetBits( &p_spudec->bit_stream, 8 ); + i_index++; + + 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. */ + 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 = GetBits( &p_spudec->bit_stream, 12 ) + - p_spu->i_x + 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 error: unknown command 0x%.2x", + i_command ); + return( 1 ); + } + + } 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 ) + { + intf_ErrMsg( "spudec error: index mismatch (0x%.4x != 0x%.4x)", + i_next_index, i_prev_index ); + return( 1 ); + } + + if( i_index > p_spudec->i_spu_size ) + { + intf_ErrMsg( "spudec error: uh-oh, we went too far (0x%.4x > 0x%.4x)", + i_index, p_spudec->i_spu_size ); + return( 1 ); + } + + /* Get rid of padding bytes */ + switch( p_spudec->i_spu_size - i_index ) + { + case 1: + + RemoveBits( &p_spudec->bit_stream, 8 ); + i_index++; + + case 0: + + /* 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 ) + { + RemoveBits( &p_spudec->bit_stream, 8 ); + i_index++; + } + + break; + } + + /* Successfully parsed ! */ + return( 0 ); } diff --git a/src/spu_decoder/spu_decoder.h b/src/spu_decoder/spu_decoder.h index 6f56fd2207..12c175334d 100644 --- a/src/spu_decoder/spu_decoder.h +++ b/src/spu_decoder/spu_decoder.h @@ -3,7 +3,7 @@ ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * - * Authors: + * Authors: Samuel Hocevar * * 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; /***************************************************************************** diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index e358705ccd..7589e4c583 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -6,7 +6,7 @@ ***************************************************************************** * Copyright (C) 2000 VideoLAN * - * Authors: + * Authors: Vincent Seguin * * 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 diff --git a/src/video_output/video_spu.c b/src/video_output/video_spu.c index bc9aa9c9b7..e00b392d72 100644 --- a/src/video_output/video_spu.c +++ b/src/video_output/video_spu.c @@ -1,11 +1,10 @@ /***************************************************************************** - * video_spu.h : DVD subpicture units functions + * video_spu.c : DVD subpicture units functions ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * - * Authors: - * Samuel "Sam" Hocevar - * Henri Fallon + * Authors: Samuel Hocevar + * Henri Fallon * * 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 @@ -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; + int i_xscale = ( p_buffer->i_pic_width << 6 ) / TARGET_WIDTH; + int i_yscale = ( 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 }; + u8 *p_source = p_spu->p_data; + u8 *p_dest; + int pi_index[2]; - boolean_t b_aligned = 1; - byte_t *p_from[2]; - vout_spu_t vspu; + pi_index[0] = ( p_spu->type.spu.i_offset[0] - 2 ) << 1; + pi_index[1] = ( p_spu->type.spu.i_offset[1] - 2 ) << 1; - 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]; + p_dest = p_buffer->p_data + /* add the picture coordinates and the SPU coordinates */ + + ( p_buffer->i_pic_x + ((p_spu->i_x * i_xscale) >> 6)) + * i_bytes_per_pixel + + ( p_buffer->i_pic_y + ((p_spu->i_y * i_yscale) >> 6)) + * i_bytes_per_line; - 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 - /* add the picture coordinates and the SPU coordinates */ - + ( p_buffer->i_pic_x + ((p_subpic->i_x * i_x_scale) >> 6)) - * i_bytes_per_pixel - + ( p_buffer->i_pic_y + ((p_subpic->i_y * i_y_scale) >> 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( pi_index[0] >> 1 < p_spu->type.spu.i_offset[1] ) { - while( p_from[0] < (byte_t *)p_subpic->p_data - + p_subpic->type.spu.i_offset[1] ) + i_code = GetNibble( p_source, pi_index + i_id ); + + if( i_code >= 0x04 ) { - GET_NIBBLE( i_code ); - - if( i_code >= 0x04 ) - { - found_code_with_scale: - - if( ((i_code >> 2) + vspu.i_x + vspu.i_y * vspu.i_width) - > vspu.i_height * vspu.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 ) ); - 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 ); - - /* 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_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) ); - 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 ) + found_code: + + if( ((i_code >> 2) + i_x + i_y * i_width) > i_height * i_width ) { - if( NewLine( &vspu, &i_id ) < 0 ) - return; - - if( !b_aligned ) - b_aligned = 1; + intf_DbgMsg ( "video_spu: invalid draw request ! %d %d", + i_code >> 2, i_height * i_width + - ( (i_code >> 2) + i_x + i_y * i_width ) ); + return; } 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: - - if( ((i_code >> 2) + vspu.i_x + vspu.i_y * vspu.i_width) - > vspu.i_height * vspu.i_width ) + if( (i_color = i_code & 0x3) ) { - 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; + 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 >> 2) * i_xscale) >> 6) + 1) + * i_bytes_per_pixel ); } - else + i_x += i_code >> 2; + } + + if( i_x >= i_width ) + { + /* byte-align the stream */ + if( pi_index[i_id] & 0x1 ) { - 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; + pi_index[i_id]++; } - - if( vspu.i_x >= vspu.i_width ) + + i_id = ~i_id & 0x1; + + i_y++; + i_x = 0; + + if( i_width <= i_y ) { - /* byte-align the stream */ - b_aligned = 1; - /* finish the line */ - NewLine( &vspu, &i_id ); + return; } - continue; } - - ADD_NIBBLE( i_code, (i_code << 4) ); - if( i_code >= 0x10 ) /* 00 11 xx cc */ - goto found_code; /* 00 01 xx cc */ - - ADD_NIBBLE( i_code, (i_code << 4) ); - 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) ); - 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 ) + continue; + } + + 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 */ + } + + 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 */ + } + + 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( i_code & ~0x0003 ) + { + /* we have a boo boo ! */ + intf_ErrMsg( "video_spu: unknown code 0x%x " + "(dest %x side %x, x=%d, y=%d)", + i_code, p_source, i_id, i_x, i_y ); + return; + } + else + { + /* if the 14 first bits are 0, then it's a new line */ + if( pi_index[i_id] & 0x1 ) { - if( NewLine( &vspu, &i_id ) < 0 ) - return; - - if( !b_aligned ) - b_aligned = 1; + pi_index[i_id]++; } - else + + i_id = ~i_id & 0x1; + + i_y++; + i_x = 0; + + if( i_width <= i_y ) { - /* 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; + return; } } } } -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++; - - return( p_vspu->i_width - p_vspu->i_y ); - -} - diff --git a/src/video_output/video_spu.h b/src/video_output/video_spu.h index 2af744343f..fa80e83e9a 100644 --- a/src/video_output/video_spu.h +++ b/src/video_output/video_spu.h @@ -3,7 +3,8 @@ ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * - * Authors: + * Authors: Samuel Hocevar + * Henri Fallon * * 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 diff --git a/src/video_output/video_text.c b/src/video_output/video_text.c index b1e3d8a04a..25a7f23a1f 100644 --- a/src/video_output/video_text.c +++ b/src/video_output/video_text.c @@ -3,7 +3,8 @@ ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * - * Authors: + * Authors: Vincent Seguin + * Samuel Hocevar * * 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 diff --git a/src/video_output/video_text.h b/src/video_output/video_text.h index af9189c81b..6a0ac2f5b0 100644 --- a/src/video_output/video_text.h +++ b/src/video_output/video_text.h @@ -3,7 +3,8 @@ ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * - * Authors: + * Authors: Vincent Seguin + * Samuel Hocevar * * 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 diff --git a/src/video_output/video_yuv.c b/src/video_output/video_yuv.c index 594310ce03..3b125eb28f 100644 --- a/src/video_output/video_yuv.c +++ b/src/video_output/video_yuv.c @@ -4,7 +4,7 @@ ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * - * Authors: + * Authors: Vincent Seguin * * 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 diff --git a/src/video_output/video_yuv.h b/src/video_output/video_yuv.h index 6a49c10deb..e9d4eb7b02 100644 --- a/src/video_output/video_yuv.h +++ b/src/video_output/video_yuv.h @@ -4,7 +4,7 @@ ***************************************************************************** * Copyright (C) 1999, 2000 VideoLAN * - * Authors: + * Authors: Vincent Seguin * * 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