[Mplayerxp-cvslog] SF.net SVN: mplayerxp:[197] mplayerxp
Brought to you by:
olov
From: <nic...@us...> - 2012-10-25 06:26:42
|
Revision: 197 http://mplayerxp.svn.sourceforge.net/mplayerxp/?rev=197&view=rev Author: nickols_k Date: 2012-10-25 06:26:33 +0000 (Thu, 25 Oct 2012) Log Message: ----------- reorder source tree Modified Paths: -------------- mplayerxp/Makefile mplayerxp/libmpcodecs/Makefile mplayerxp/libmpdemux/Makefile mplayerxp/libmpdemux/demux_mkv.c mplayerxp/libmpdemux/demux_mpxp64.c mplayerxp/libmpdemux/demux_ogg.c mplayerxp/libmpdemux/demuxer.c mplayerxp/libmpdemux/s_dvdnav.c mplayerxp/libmpdemux/sub_cc.c mplayerxp/libvo/sub.c mplayerxp/libvo/video_out.h Added Paths: ----------- mplayerxp/libmpsub/ mplayerxp/libmpsub/Makefile mplayerxp/libmpsub/find_sub.c mplayerxp/libmpsub/spudec.c mplayerxp/libmpsub/spudec.h mplayerxp/libmpsub/subreader.c mplayerxp/libmpsub/subreader.h mplayerxp/libmpsub/vobsub.c mplayerxp/libmpsub/vobsub.h Removed Paths: ------------- mplayerxp/find_sub.c mplayerxp/spudec.c mplayerxp/spudec.h mplayerxp/subreader.c mplayerxp/subreader.h mplayerxp/vobsub.c mplayerxp/vobsub.h Modified: mplayerxp/Makefile =================================================================== --- mplayerxp/Makefile 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/Makefile 2012-10-25 06:26:33 UTC (rev 197) @@ -13,7 +13,7 @@ PRG_FIBMAP = fibmap_mplayerxp PRG_CFG = codec-cfg-xp # these subdirectories required installation due binaries within them -SUBDIRS = libmpdemux libmpcodecs libao2 osdep postproc input nls libvo +SUBDIRS = libmpdemux libmpsub libmpcodecs libao2 osdep postproc input nls libvo ifeq ($(TARGET_ARCH_X86),yes) SUBDIRS+=loader endif @@ -23,8 +23,8 @@ MANDIR = ${prefix}/man LDFLAGS += -Wl,-rpath,${CODECDIR}/codecs -SRCS_COMMON = cpudetect.c mp_msg.c codec-cfg.c cfgparser.c my_profile.c my_malloc.c spudec.c playtree.c playtreeparser.c asxparser.c mp_image.c subopt-helper.c -SRCS_MPLAYER = mplayer.c fifo.c $(SRCS_COMMON) find_sub.c subreader.c mixer.c vobsub.c mp-opt-reg.c sig_hand.c dump.c dec_ahead.c m_option.c m_property.c m_struct.c +SRCS_COMMON = cpudetect.c mp_msg.c codec-cfg.c cfgparser.c my_profile.c my_malloc.c playtree.c playtreeparser.c asxparser.c mp_image.c subopt-helper.c +SRCS_MPLAYER = mplayer.c fifo.c $(SRCS_COMMON) mixer.c mp-opt-reg.c sig_hand.c dump.c dec_ahead.c m_option.c m_property.c m_struct.c OBJS_MPLAYER = $(SRCS_MPLAYER:.c=.o) @@ -36,6 +36,7 @@ MP_LIBS = libmpdemux/libmpdemux.a \ libmpcodecs/libmpcodecs.a \ + libmpsub/libmpsub.a \ libao2/libao2.a \ postproc/libpostproc.a \ input/libinput.a \ @@ -47,7 +48,7 @@ endif COMMON_LIBS = $(MP_LIBS) $(FF_LIBS) $(EXTRALIBS) -lm -CFLAGS = $(OPTFLAGS) -Ilibmpdemux -Ilibvo $(EXTRA_INC) +CFLAGS = $(OPTFLAGS) -Ilibmpsub -Ilibmpdemux -Ilibvo $(EXTRA_INC) ALL_PRG = $(PRG) ifeq ($(HAVE_CSS),yes) Deleted: mplayerxp/find_sub.c =================================================================== --- mplayerxp/find_sub.c 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/find_sub.c 2012-10-25 06:26:33 UTC (rev 197) @@ -1,111 +0,0 @@ -//**************************************************************************// -// .SUB -//**************************************************************************// - -#include "mp_config.h" - -#ifdef USE_OSD - -#include <stdio.h> -#include <limits.h> -#include "libvo/video_out.h" -#include "libvo/sub.h" -#include "subreader.h" -#define MSGT_CLASS MSGT_FINDSUB -#include "__mp_msg.h" - -static int current_sub=0; - -//static subtitle* subtitles=NULL; -static unsigned long nosub_range_start=ULONG_MAX; -static unsigned long nosub_range_end=ULONG_MAX; - -void find_sub(subtitle* subtitles,unsigned long key,any_t*vo_data){ - int i,j; - vo_data_t*vo=vo_data; - - if ( !subtitles ) return; - - if(vo->sub){ - if(key>=vo->sub->start && key<=vo->sub->end) return; // OK! - } else { - if(key>nosub_range_start && key<nosub_range_end) return; // OK! - } - // sub changed! - - /* Tell the OSD subsystem that the OSD contents will change soon */ - vo_osd_changed(OSDTYPE_SUBTITLE); - - if(key<=0){ - vo->sub=NULL; // no sub here - return; - } - - // check next sub. - if(current_sub>=0 && current_sub+1<sub_num){ - if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){ - // no sub - nosub_range_start=subtitles[current_sub].end; - nosub_range_end=subtitles[current_sub+1].start; - vo->sub=NULL; - return; - } - // next sub? - ++current_sub; - vo->sub=&subtitles[current_sub]; - if(key>=vo->sub->start && key<=vo->sub->end) return; // OK! - } - - // use logarithmic search: - i=0;j=sub_num-1; - while(j>=i){ - current_sub=(i+j+1)/2; - vo->sub=&subtitles[current_sub]; - if(key<vo->sub->start) j=current_sub-1; - else if(key>vo->sub->end) i=current_sub+1; - else return; // found! - } -// if(key>=vo->sub->start && key<=vo->sub->end) return; // OK! - - // check where are we... - if(key<vo->sub->start){ - if(current_sub<=0){ - // before the first sub - nosub_range_start=key-1; // tricky - nosub_range_end=vo->sub->start; - vo->sub=NULL; - return; - } - --current_sub; - if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){ - // no sub - nosub_range_start=subtitles[current_sub].end; - nosub_range_end=subtitles[current_sub+1].start; - vo->sub=NULL; - return; - } - MSG_V("HEH???? "); - } else { - if(key<=vo->sub->end) MSG_V("JAJJ! "); else - if(current_sub+1>=sub_num){ - // at the end? - nosub_range_start=vo->sub->end; - nosub_range_end=0x7FFFFFFF; // MAXINT - vo->sub=NULL; - return; - } else - if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){ - // no sub - nosub_range_start=subtitles[current_sub].end; - nosub_range_end=subtitles[current_sub+1].start; - vo->sub=NULL; - return; - } - } - - MSG_ERR("SUB ERROR: %d ? %d --- %d [%d] \n",key,(int)vo->sub->start,(int)vo->sub->end,current_sub); - - vo->sub=NULL; // no sub here -} - -#endif Modified: mplayerxp/libmpcodecs/Makefile =================================================================== --- mplayerxp/libmpcodecs/Makefile 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpcodecs/Makefile 2012-10-25 06:26:33 UTC (rev 197) @@ -55,7 +55,7 @@ OBJS=$(SRCS:.c=.o) -CFLAGS = $(OPTFLAGS) -I. -I.. -I../libmpdemux -I../loader -Wall +CFLAGS = $(OPTFLAGS) -I. -I.. -I../libmpdemux -I../libmpsub -I../loader -Wall .SUFFIXES: .c .o Modified: mplayerxp/libmpdemux/Makefile =================================================================== --- mplayerxp/libmpdemux/Makefile 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpdemux/Makefile 2012-10-25 06:26:33 UTC (rev 197) @@ -54,7 +54,7 @@ endif OBJS = $(SRCS:.c=.o) -INCLUDE = -I../loader +INCLUDE = -I../libmpsub -I../loader CFLAGS = $(OPTFLAGS) $(INCLUDE) -W -Wall .SUFFIXES: .c .o Modified: mplayerxp/libmpdemux/demux_mkv.c =================================================================== --- mplayerxp/libmpdemux/demux_mkv.c 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpdemux/demux_mkv.c 2012-10-25 06:26:33 UTC (rev 197) @@ -22,8 +22,8 @@ #include <dlfcn.h> #include "../bswap.h" -#include "../vobsub.h" -#include "../subreader.h" +#include "vobsub.h" +#include "subreader.h" #include "../libvo/sub.h" #include "../libmpcodecs/codecs_ld.h" #include "../libmpcodecs/libnuppelvideo/minilzo.h" Modified: mplayerxp/libmpdemux/demux_mpxp64.c =================================================================== --- mplayerxp/libmpdemux/demux_mpxp64.c 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpdemux/demux_mpxp64.c 2012-10-25 06:26:33 UTC (rev 197) @@ -17,7 +17,7 @@ #include "stheader.h" #include "loader/qtx/qtxsdk/components.h" #include "../nls/nls.h" -#include "../subreader.h" +#include "subreader.h" #include "bswap.h" #include "aviheader.h" Modified: mplayerxp/libmpdemux/demux_ogg.c =================================================================== --- mplayerxp/libmpdemux/demux_ogg.c 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpdemux/demux_ogg.c 2012-10-25 06:26:33 UTC (rev 197) @@ -149,7 +149,7 @@ //-------- subtitle support - should be moved to decoder layer, and queue // - subtitles up in demuxer buffer... -#include "../subreader.h" +#include "subreader.h" #include "../libvo/sub.h" #define OGG_SUB_MAX_LINE 128 Modified: mplayerxp/libmpdemux/demuxer.c =================================================================== --- mplayerxp/libmpdemux/demuxer.c 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpdemux/demuxer.c 2012-10-25 06:26:33 UTC (rev 197) @@ -13,7 +13,7 @@ #include "../mp_config.h" #include "help_mp.h" #include "../mplayer.h" -#include "../subreader.h" +#include "subreader.h" #include "../cfgparser.h" #include "../nls/nls.h" Modified: mplayerxp/libmpdemux/s_dvdnav.c =================================================================== --- mplayerxp/libmpdemux/s_dvdnav.c 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpdemux/s_dvdnav.c 2012-10-25 06:26:33 UTC (rev 197) @@ -9,7 +9,7 @@ #include "stream.h" #include "help_mp.h" #include "demuxer.h" -#include "../spudec.h" +#include "spudec.h" #include "../libvo/sub.h" #include "../input/input.h" #include "../mplayer.h" Modified: mplayerxp/libmpdemux/sub_cc.c =================================================================== --- mplayerxp/libmpdemux/sub_cc.c 2012-10-24 16:30:14 UTC (rev 196) +++ mplayerxp/libmpdemux/sub_cc.c 2012-10-25 06:26:33 UTC (rev 197) @@ -20,7 +20,7 @@ #include "../mp_config.h" #include "sub_cc.h" -#include "../subreader.h" +#include "subreader.h" #include "../libvo/video_out.h" #include "../libvo/sub.h" Added: mplayerxp/libmpsub/Makefile =================================================================== --- mplayerxp/libmpsub/Makefile (rev 0) +++ mplayerxp/libmpsub/Makefile 2012-10-25 06:26:33 UTC (rev 197) @@ -0,0 +1,49 @@ + +LIBNAME = libmpsub.a + +include ../mp_config.mak + +DO_MAKE = @ for i in $(SUBDIRS); do $(MAKE) -C $$i $@ || exit; done +DO_ALL = @ for i in $(SUBDIRS); do $(MAKE) -C $$i all || exit; done + +SRCS = find_sub.c spudec.c subreader.c vobsub.c + +OBJS = $(SRCS:.c=.o) +INCLUDE = -I. -I../ +CFLAGS = $(OPTFLAGS) $(INCLUDE) -W -Wall + +.SUFFIXES: .c .o + +.PHONY: $(SUBDIRS) + +all: $(LIBNAME) + +$(SUBDIRS): + $(DO_ALL) + +.c.o: + $(CC) -c $(CFLAGS) -o $@ $< + +$(LIBNAME): $(SUBDIRS) $(OBJS) + $(AR) r $(LIBNAME) $(OBJS) + +clean: + $(DO_MAKE) + rm -f *.o *.a *~ + +distclean: + $(DO_MAKE) + rm -f test Makefile.bak *.o *.a *~ .depend + +dep: depend + +depend: + $(DO_MAKE) + $(CC) -MM $(CFLAGS) $(SRCS) 1>.depend + +# +# include dependency files if they exist +# +ifneq ($(wildcard .depend),) +include .depend +endif Property changes on: mplayerxp/libmpsub/Makefile ___________________________________________________________________ Added: svn:eol-style + native Copied: mplayerxp/libmpsub/find_sub.c (from rev 192, mplayerxp/find_sub.c) =================================================================== --- mplayerxp/libmpsub/find_sub.c (rev 0) +++ mplayerxp/libmpsub/find_sub.c 2012-10-25 06:26:33 UTC (rev 197) @@ -0,0 +1,111 @@ +//**************************************************************************// +// .SUB +//**************************************************************************// + +#include "mp_config.h" + +#ifdef USE_OSD + +#include <stdio.h> +#include <limits.h> +#include "libvo/video_out.h" +#include "libvo/sub.h" +#include "subreader.h" +#define MSGT_CLASS MSGT_FINDSUB +#include "__mp_msg.h" + +static int current_sub=0; + +//static subtitle* subtitles=NULL; +static unsigned long nosub_range_start=ULONG_MAX; +static unsigned long nosub_range_end=ULONG_MAX; + +void find_sub(subtitle* subtitles,unsigned long key,any_t*vo_data){ + int i,j; + vo_data_t*vo=vo_data; + + if ( !subtitles ) return; + + if(vo->sub){ + if(key>=vo->sub->start && key<=vo->sub->end) return; // OK! + } else { + if(key>nosub_range_start && key<nosub_range_end) return; // OK! + } + // sub changed! + + /* Tell the OSD subsystem that the OSD contents will change soon */ + vo_osd_changed(OSDTYPE_SUBTITLE); + + if(key<=0){ + vo->sub=NULL; // no sub here + return; + } + + // check next sub. + if(current_sub>=0 && current_sub+1<sub_num){ + if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){ + // no sub + nosub_range_start=subtitles[current_sub].end; + nosub_range_end=subtitles[current_sub+1].start; + vo->sub=NULL; + return; + } + // next sub? + ++current_sub; + vo->sub=&subtitles[current_sub]; + if(key>=vo->sub->start && key<=vo->sub->end) return; // OK! + } + + // use logarithmic search: + i=0;j=sub_num-1; + while(j>=i){ + current_sub=(i+j+1)/2; + vo->sub=&subtitles[current_sub]; + if(key<vo->sub->start) j=current_sub-1; + else if(key>vo->sub->end) i=current_sub+1; + else return; // found! + } +// if(key>=vo->sub->start && key<=vo->sub->end) return; // OK! + + // check where are we... + if(key<vo->sub->start){ + if(current_sub<=0){ + // before the first sub + nosub_range_start=key-1; // tricky + nosub_range_end=vo->sub->start; + vo->sub=NULL; + return; + } + --current_sub; + if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){ + // no sub + nosub_range_start=subtitles[current_sub].end; + nosub_range_end=subtitles[current_sub+1].start; + vo->sub=NULL; + return; + } + MSG_V("HEH???? "); + } else { + if(key<=vo->sub->end) MSG_V("JAJJ! "); else + if(current_sub+1>=sub_num){ + // at the end? + nosub_range_start=vo->sub->end; + nosub_range_end=0x7FFFFFFF; // MAXINT + vo->sub=NULL; + return; + } else + if(key>subtitles[current_sub].end && key<subtitles[current_sub+1].start){ + // no sub + nosub_range_start=subtitles[current_sub].end; + nosub_range_end=subtitles[current_sub+1].start; + vo->sub=NULL; + return; + } + } + + MSG_ERR("SUB ERROR: %d ? %d --- %d [%d] \n",key,(int)vo->sub->start,(int)vo->sub->end,current_sub); + + vo->sub=NULL; // no sub here +} + +#endif Copied: mplayerxp/libmpsub/spudec.c (from rev 192, mplayerxp/spudec.c) =================================================================== --- mplayerxp/libmpsub/spudec.c (rev 0) +++ mplayerxp/libmpsub/spudec.c 2012-10-25 06:26:33 UTC (rev 197) @@ -0,0 +1,1183 @@ +/* SPUdec.c + Skeleton of function spudec_process_controll() is from xine sources. + Further works: + LGB,... (yeah, try to improve it and insert your name here! ;-) + + Kim Minh Kaplan + implement fragments reassembly, RLE decoding. + read brightness from the IFO. + + For information on SPU format see <URL:http://sam.zoy.org/doc/dvd/subtitles/> + and <URL:http://members.aol.com/mpucoder/DVD/spu.html> + + */ +#include "mp_config.h" + +#include <errno.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <math.h> + +#include "dec_ahead.h" +#include "spudec.h" +#include "postproc/swscale.h" +#define MSGT_CLASS MSGT_SPUDEC +#include "__mp_msg.h" + +#ifndef MIN +#define MIN(a, b) ((a)<(b)?(a):(b)) +#endif + +/* Valid values for spu_aamode: + 0: none (fastest, most ugly) + 1: approximate + 2: full (slowest) + 3: bilinear (similiar to vobsub, fast and not too bad) + 4: uses swscaler gaussian (this is the only one that looks good) + */ + +int spu_aamode = 3; +int spu_alignment = -1; +float spu_gaussvar = 1.0; + +typedef struct packet_t packet_t; +struct packet_t { + unsigned char *packet; + unsigned int palette[4]; + unsigned int alpha[4]; + unsigned int control_start; /* index of start of control data */ + unsigned int current_nibble[2]; /* next data nibble (4 bits) to be + processed (for RLE decoding) for + even and odd lines */ + int deinterlace_oddness; /* 0 or 1, index into current_nibble */ + unsigned int start_col, end_col; + unsigned int start_row, end_row; + unsigned int width, height, stride; + unsigned int start_pts, end_pts; + packet_t *next; +}; + +typedef struct { + packet_t *queue_head; + packet_t *queue_tail; + unsigned int global_palette[16]; + unsigned int orig_frame_width, orig_frame_height; + unsigned char* packet; + size_t packet_reserve; /* size of the memory pointed to by packet */ + unsigned int packet_offset; /* end of the currently assembled fragment */ + unsigned int packet_size; /* size of the packet once all fragments are assembled */ + unsigned int packet_pts; /* PTS for this packet */ + unsigned int palette[4]; + unsigned int alpha[4]; + unsigned int cuspal[4]; + unsigned int custom; + unsigned int now_pts; + unsigned int start_pts, end_pts; + unsigned int start_col, end_col; + unsigned int start_row, end_row; + unsigned int width, height, stride; + size_t image_size; /* Size of the image buffer */ + unsigned char *image; /* Grayscale value */ + unsigned char *aimage; /* Alpha value */ + unsigned int scaled_frame_width, scaled_frame_height; + unsigned int scaled_start_col, scaled_start_row; + unsigned int scaled_width, scaled_height, scaled_stride; + size_t scaled_image_size; + unsigned char *scaled_image; + unsigned char *scaled_aimage; + int auto_palette; /* 1 if we lack a palette and must use an heuristic. */ + int font_start_level; /* Darkest value used for the computed font */ + vo_functions_t *hw_spu; + int spu_changed; + unsigned int forced_subs_only; /* flag: 0=display all subtitle, !0 display only forced subtitles */ + unsigned int is_forced_sub; /* true if current subtitle is a forced subtitle */ +} spudec_handle_t; + +static void __FASTCALL__ spudec_queue_packet(spudec_handle_t *this, packet_t *packet) +{ + if (this->queue_head == NULL) + this->queue_head = packet; + else + this->queue_tail->next = packet; + this->queue_tail = packet; +} + +static packet_t __FASTCALL__ *spudec_dequeue_packet(spudec_handle_t *this) +{ + packet_t *retval = this->queue_head; + + this->queue_head = retval->next; + if (this->queue_head == NULL) + this->queue_tail = NULL; + + return retval; +} + +static void __FASTCALL__ spudec_free_packet(packet_t *packet) +{ + if (packet->packet != NULL) + free(packet->packet); + free(packet); +} + +static inline unsigned int __FASTCALL__ get_be16(const unsigned char *p) +{ + return (p[0] << 8) + p[1]; +} + +static inline unsigned int __FASTCALL__ get_be24(const unsigned char *p) +{ + return (get_be16(p) << 8) + p[2]; +} + +static void __FASTCALL__ next_line(packet_t *packet) +{ + if (packet->current_nibble[packet->deinterlace_oddness] % 2) + packet->current_nibble[packet->deinterlace_oddness]++; + packet->deinterlace_oddness = (packet->deinterlace_oddness + 1) % 2; +} + +static inline unsigned char __FASTCALL__ get_nibble(packet_t *packet) +{ + unsigned char nib; + unsigned int *nibblep = packet->current_nibble + packet->deinterlace_oddness; + if (*nibblep / 2 >= packet->control_start) { + MSG_WARN( "SPUdec: ERROR: get_nibble past end of packet\n"); + return 0; + } + nib = packet->packet[*nibblep / 2]; + if (*nibblep % 2) + nib &= 0xf; + else + nib >>= 4; + ++*nibblep; + return nib; +} + +static inline int __FASTCALL__ mkalpha(int i) +{ + /* In mplayer's alpha planes, 0 is transparent, then 1 is nearly + opaque upto 255 which is transparent */ + switch (i) { + case 0xf: + return 1; + case 0: + return 0; + default: + return (0xf - i) << 4; + } +} + +/* Cut the sub to visible part */ +static inline void __FASTCALL__ spudec_cut_image(spudec_handle_t *this) +{ + unsigned int fy, ly; + unsigned int first_y, last_y; + unsigned char *image; + unsigned char *aimage; + + if (this->stride == 0 || this->height == 0) { + return; + } + + for (fy = 0; fy < this->image_size && !this->aimage[fy]; fy++); + for (ly = this->stride * this->height-1; ly && !this->aimage[ly]; ly--); + first_y = fy / this->stride; + last_y = ly / this->stride; + //printf("first_y: %d, last_y: %d\n", first_y, last_y); + this->start_row += first_y; + + // Some subtitles trigger this condition + if (last_y + 1 > first_y ) { + this->height = last_y - first_y +1; + } else { + this->height = 0; + this->image_size = 0; + return; + } + +// printf("new h %d new start %d (sz %d st %d)---\n\n", this->height, this->start_row, this->image_size, this->stride); + + image = malloc(2 * this->stride * this->height); + if(image){ + this->image_size = this->stride * this->height; + aimage = image + this->image_size; + memcpy(image, this->image + this->stride * first_y, this->image_size); + memcpy(aimage, this->aimage + this->stride * first_y, this->image_size); + free(this->image); + this->image = image; + this->aimage = aimage; + } else { + MSG_FATAL("Fatal: update_spu: malloc requested %d bytes\n", 2 * this->stride * this->height); + } +} + +static void __FASTCALL__ spudec_process_data(spudec_handle_t *this, packet_t *packet) +{ + unsigned int cmap[4], alpha[4]; + unsigned int i, x, y; + + this->scaled_frame_width = 0; + this->scaled_frame_height = 0; + this->start_col = packet->start_col; + this->end_col = packet->end_col; + this->start_row = packet->start_row; + this->end_row = packet->end_row; + this->height = packet->height; + this->width = packet->width; + this->stride = packet->stride; + for (i = 0; i < 4; ++i) { + alpha[i] = mkalpha(packet->alpha[i]); + if (alpha[i] == 0) + cmap[i] = 0; + else if (this->custom){ + cmap[i] = ((this->cuspal[i] >> 16) & 0xff); + if (cmap[i] + alpha[i] > 255) + cmap[i] = 256 - alpha[i]; + } + else { + cmap[i] = ((this->global_palette[packet->palette[i]] >> 16) & 0xff); + if (cmap[i] + alpha[i] > 255) + cmap[i] = 256 - alpha[i]; + } + } + + if (this->image_size < this->stride * this->height) { + if (this->image != NULL) { + free(this->image); + this->image_size = 0; + } + this->image = malloc(2 * this->stride * this->height); + if (this->image) { + this->image_size = this->stride * this->height; + this->aimage = this->image + this->image_size; + } + } + if (this->image == NULL) + return; + + /* Kludge: draw_alpha needs width multiple of 8. */ + if (this->width < this->stride) + for (y = 0; y < this->height; ++y) + memset(this->aimage + y * this->stride + this->width, 0, this->stride - this->width); + + i = packet->current_nibble[1]; + x = 0; + y = 0; + while (packet->current_nibble[0] < i + && packet->current_nibble[1] / 2 < packet->control_start + && y < this->height) { + unsigned int len, color; + unsigned int rle = 0; + rle = get_nibble(packet); + if (rle < 0x04) { + rle = (rle << 4) | get_nibble(packet); + if (rle < 0x10) { + rle = (rle << 4) | get_nibble(packet); + if (rle < 0x040) { + rle = (rle << 4) | get_nibble(packet); + if (rle < 0x0004) + rle |= ((this->width - x) << 2); + } + } + } + color = 3 - (rle & 0x3); + len = rle >> 2; + if (len > this->width - x || len == 0) + len = this->width - x; + /* FIXME have to use palette and alpha map*/ + memset(this->image + y * this->stride + x, cmap[color], len); + memset(this->aimage + y * this->stride + x, alpha[color], len); + x += len; + if (x >= this->width) { + next_line(packet); + x = 0; + ++y; + } + } + spudec_cut_image(this); +} + + +/* + This function tries to create a usable palette. + It determines how many non-transparent colors are used, and assigns different +gray scale values to each color. + I tested it with four streams and even got something readable. Half of the +times I got black characters with white around and half the reverse. +*/ +static void __FASTCALL__ compute_palette(spudec_handle_t *this, packet_t *packet) +{ + int used[16],i,cused,start,step,color; + + memset(used, 0, sizeof(used)); + for (i=0; i<4; i++) + if (packet->alpha[i]) /* !Transparent? */ + used[packet->palette[i]] = 1; + for (cused=0, i=0; i<16; i++) + if (used[i]) cused++; + if (!cused) return; + if (cused == 1) { + start = 0x80; + step = 0; + } else { + start = this->font_start_level; + step = (0xF0-this->font_start_level)/(cused-1); + } + memset(used, 0, sizeof(used)); + for (i=0; i<4; i++) { + color = packet->palette[i]; + if (packet->alpha[i] && !used[color]) { /* not assigned? */ + used[color] = 1; + this->global_palette[color] = start<<16; + start += step; + } + } +} + +static void __FASTCALL__ spudec_process_control(spudec_handle_t *this, unsigned int pts100) +{ + int a,b; /* Temporary vars */ + unsigned int date, type; + unsigned int off; + unsigned int start_off = 0; + unsigned int next_off; + unsigned int start_pts=0; + unsigned int end_pts=0; + unsigned int current_nibble[2] = { 0, 0 }; + unsigned int control_start; + unsigned int display = 0; + unsigned int start_col = 0; + unsigned int end_col = 0; + unsigned int start_row = 0; + unsigned int end_row = 0; + unsigned int width = 0; + unsigned int height = 0; + unsigned int stride = 0; + + control_start = get_be16(this->packet + 2); + next_off = control_start; + while (start_off != next_off) { + start_off = next_off; + date = get_be16(this->packet + start_off) * 1024; + next_off = get_be16(this->packet + start_off + 2); + MSG_DBG2( "date=%d\n", date); + off = start_off + 4; + for (type = this->packet[off++]; type != 0xff; type = this->packet[off++]) { + MSG_DBG2( "cmd=%d ",type); + switch(type) { + case 0x00: + /* Menu ID, 1 byte */ + MSG_DBG2("Menu ID\n"); + /* shouldn't a Menu ID type force display start? */ + start_pts = pts100 + date; + end_pts = UINT_MAX; + display = 1; + this->is_forced_sub=~0; // current subtitle is forced + break; + case 0x01: + /* Start display */ + MSG_DBG2("Start display!\n"); + start_pts = pts100 + date; + end_pts = UINT_MAX; + display = 1; + this->is_forced_sub=0; + break; + case 0x02: + /* Stop display */ + MSG_DBG2("Stop display!\n"); + end_pts = pts100 + date; + break; + case 0x03: + /* Palette */ + this->palette[0] = this->packet[off] >> 4; + this->palette[1] = this->packet[off] & 0xf; + this->palette[2] = this->packet[off + 1] >> 4; + this->palette[3] = this->packet[off + 1] & 0xf; + MSG_DBG2("Palette %d, %d, %d, %d\n", + this->palette[0], this->palette[1], this->palette[2], this->palette[3]); + off+=2; + break; + case 0x04: + /* Alpha */ + this->alpha[0] = this->packet[off] >> 4; + this->alpha[1] = this->packet[off] & 0xf; + this->alpha[2] = this->packet[off + 1] >> 4; + this->alpha[3] = this->packet[off + 1] & 0xf; + MSG_DBG2("Alpha %d, %d, %d, %d\n", + this->alpha[0], this->alpha[1], this->alpha[2], this->alpha[3]); + off+=2; + break; + case 0x05: + /* Co-ords */ + a = get_be24(this->packet + off); + b = get_be24(this->packet + off + 3); + start_col = a >> 12; + end_col = a & 0xfff; + width = (end_col < start_col) ? 0 : end_col - start_col + 1; + stride = (width + 7) & ~7; /* Kludge: draw_alpha needs width multiple of 8 */ + start_row = b >> 12; + end_row = b & 0xfff; + height = (end_row < start_row) ? 0 : end_row - start_row /* + 1 */; + MSG_DBG2("Coords col: %d - %d row: %d - %d (%dx%d)\n", + start_col, end_col, start_row, end_row, + width, height); + off+=6; + break; + case 0x06: + /* Graphic lines */ + current_nibble[0] = 2 * get_be16(this->packet + off); + current_nibble[1] = 2 * get_be16(this->packet + off + 2); + MSG_DBG2("Graphic offset 1: %d offset 2: %d\n", + current_nibble[0] / 2, current_nibble[1] / 2); + off+=4; + break; + case 0xff: + /* All done, bye-bye */ + MSG_DBG2("Done!\n"); + return; +// break; + default: + MSG_WARN("spudec: Error determining control type 0x%02x. Skipping %d bytes.\n", + type, next_off - off); + goto next_control; + } + } + next_control: + if (display) { + packet_t *packet = calloc(1, sizeof(packet_t)); + int i; + packet->start_pts = start_pts; + if (end_pts == UINT_MAX && start_off != next_off) { + start_pts = pts100 + get_be16(this->packet + next_off) * 1024; + packet->end_pts = start_pts - 1; + } else packet->end_pts = end_pts; + packet->current_nibble[0] = current_nibble[0]; + packet->current_nibble[1] = current_nibble[1]; + packet->start_row = start_row; + packet->end_row = end_row; + packet->start_col = start_col; + packet->end_col = end_col; + packet->width = width; + packet->height = height; + packet->stride = stride; + packet->control_start = control_start; + for (i=0; i<4; i++) { + packet->alpha[i] = this->alpha[i]; + packet->palette[i] = this->palette[i]; + } + packet->packet = malloc(this->packet_size); + memcpy(packet->packet, this->packet, this->packet_size); + spudec_queue_packet(this, packet); + } + } +} + +static void __FASTCALL__ spudec_decode(spudec_handle_t *this, unsigned int pts100) +{ + if(this->hw_spu) { + vo_mpegpes_t packet = { NULL, 0, 0x20, 0 }; + packet.data = this->packet; + packet.size = this->packet_size; + packet.timestamp = pts100; +// this->hw_spu->draw_frame((uint8_t**)&pkg); + } else + spudec_process_control(this, pts100); +} + +int __FASTCALL__ spudec_changed(any_t* this) +{ + spudec_handle_t * spu = (spudec_handle_t*)this; + return (spu->spu_changed || spu->now_pts > spu->end_pts); +} + +void __FASTCALL__ spudec_assemble(any_t*this, unsigned char *packet, unsigned int len, unsigned int pts100) +{ + spudec_handle_t *spu = (spudec_handle_t*)this; +// spudec_heartbeat(this, pts100); + if (len < 2) { + MSG_WARN("SPUasm: packet too short\n"); + return; + } + spu->packet_pts = pts100; + if (spu->packet_offset == 0) { + unsigned int len2 = get_be16(packet); + // Start new fragment + if (spu->packet_reserve < len2) { + if (spu->packet != NULL) + free(spu->packet); + spu->packet = malloc(len2); + spu->packet_reserve = spu->packet != NULL ? len2 : 0; + } + if (spu->packet != NULL) { + spu->packet_size = len2; + if (len > len2) { + MSG_WARN("SPUasm: invalid frag len / len2: %d / %d \n", len, len2); + return; + } + memcpy(spu->packet, packet, len); + spu->packet_offset = len; + spu->packet_pts = pts100; + } + } else { + // Continue current fragment + if (spu->packet_size < spu->packet_offset + len){ + MSG_WARN("SPUasm: invalid fragment\n"); + spu->packet_size = spu->packet_offset = 0; + return; + } else { + memcpy(spu->packet + spu->packet_offset, packet, len); + spu->packet_offset += len; + } + } +#if 1 + // check if we have a complete packet (unfortunatelly packet_size is bad + // for some disks) + // [cb] packet_size is padded to be even -> may be one byte too long + if ((spu->packet_offset == spu->packet_size) || + ((spu->packet_offset + 1) == spu->packet_size)){ + unsigned int x=0,y; + while(x+4<=spu->packet_offset){ + y=get_be16(spu->packet+x+2); // next control pointer + MSG_DBG2("SPUtest: x=%d y=%d off=%d size=%d\n",x,y,spu->packet_offset,spu->packet_size); + if(x>=4 && x==y){ // if it points to self - we're done! + // we got it! + MSG_DBG2("SPUgot: off=%d size=%d \n",spu->packet_offset,spu->packet_size); + spudec_decode(spu, pts100); + spu->packet_offset = 0; + break; + } + if(y<=x || y>=spu->packet_size){ // invalid? + MSG_WARN("SPUtest: broken packet!!!!! y=%d < x=%d\n",y,x); + spu->packet_size = spu->packet_offset = 0; + break; + } + x=y; + } + // [cb] packet is done; start new packet + spu->packet_offset = 0; + } +#else + if (spu->packet_offset == spu->packet_size) { + spudec_decode(spu, pts100); + spu->packet_offset = 0; + } +#endif +} + +void __FASTCALL__ spudec_reset(any_t*this) // called after seek +{ + spudec_handle_t *spu = (spudec_handle_t*)this; + while (spu->queue_head) + spudec_free_packet(spudec_dequeue_packet(spu)); + spu->now_pts = 0; + spu->end_pts = 0; + spu->packet_size = spu->packet_offset = 0; +} + +void __FASTCALL__ spudec_now_pts(any_t*this, unsigned int pts100) +{ + spudec_handle_t *spu = (spudec_handle_t*) this; + spu->now_pts = pts100; +} + +void __FASTCALL__ spudec_heartbeat(any_t*this, unsigned int pts100) +{ + spudec_handle_t *spu = (spudec_handle_t*) this; + spu->now_pts = pts100; + + while (spu->queue_head != NULL && pts100 >= spu->queue_head->start_pts) { + packet_t *packet = spudec_dequeue_packet(spu); + spu->start_pts = packet->start_pts; + spu->end_pts = packet->end_pts; + if (spu->auto_palette) + compute_palette(spu, packet); + spudec_process_data(spu, packet); + spudec_free_packet(packet); + spu->spu_changed = 1; + } +} + +int __FASTCALL__ spudec_visible(any_t*this){ + spudec_handle_t *spu = (spudec_handle_t *)this; + int ret=(spu->start_pts <= spu->now_pts && + spu->now_pts < spu->end_pts && + spu->height > 0); + return ret; +} + +void __FASTCALL__ spudec_set_forced_subs_only(any_t* const this, const unsigned int flag) +{ + if(this){ + ((spudec_handle_t *)this)->forced_subs_only=flag; + MSG_DBG2("SPU: Display only forced subs now %s\n", flag ? "enabled": "disabled"); + } +} + +void __FASTCALL__ spudec_draw(any_t*this, draw_osd_f draw_alpha,any_t*vo) +{ + spudec_handle_t *spu = (spudec_handle_t *)this; + if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts && spu->image) + { + draw_alpha(vo,dae_curr_vdecoded(),spu->start_col, spu->start_row, spu->width, spu->height, + spu->image, spu->aimage, spu->stride); + spu->spu_changed = 0; + } +} + +/* calc the bbox for spudec subs */ +void __FASTCALL__ spudec_calc_bbox(any_t*me, unsigned int dxs, unsigned int dys, unsigned int* bbox) +{ + spudec_handle_t *spu; + spu = (spudec_handle_t *)me; + if (spu->orig_frame_width == 0 || spu->orig_frame_height == 0 + || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys)) { + bbox[0] = spu->start_col; + bbox[1] = spu->start_col + spu->width; + bbox[2] = spu->start_row; + bbox[3] = spu->start_row + spu->height; + } + else if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) { + unsigned int scalex = 0x100 * dxs / spu->orig_frame_width; + unsigned int scaley = 0x100 * dys / spu->orig_frame_height; + bbox[0] = spu->start_col * scalex / 0x100; + bbox[1] = spu->start_col * scalex / 0x100 + spu->width * scalex / 0x100; + switch (spu_alignment) { + case 0: + bbox[3] = dys*sub_data.pos/100 + spu->height * scaley / 0x100; + if (bbox[3] > dys) bbox[3] = dys; + bbox[2] = bbox[3] - spu->height * scaley / 0x100; + break; + case 1: + if (sub_data.pos < 50) { + bbox[2] = dys*sub_data.pos/100 - spu->height * scaley / 0x200; + if ((int)(bbox[2]) < 0) bbox[2] = 0; + bbox[3] = bbox[2] + spu->height; + } else { + bbox[3] = dys*sub_data.pos/100 + spu->height * scaley / 0x200; + if (bbox[3] > dys) bbox[3] = dys; + bbox[2] = bbox[3] - spu->height * scaley / 0x100; + } + break; + case 2: + bbox[2] = dys*sub_data.pos/100 - spu->height * scaley / 0x100; + if ((int)(bbox[2]) < 0) bbox[2] = 0; + bbox[3] = bbox[2] + spu->height; + break; + default: /* -1 */ + bbox[2] = spu->start_row * scaley / 0x100; + bbox[3] = spu->start_row * scaley / 0x100 + spu->height * scaley / 0x100; + break; + } + } +} + +/* transform mplayer's alpha value into an opacity value that is linear */ +static inline int __FASTCALL__ canon_alpha(int alpha) +{ + return alpha ? 256 - alpha : 0; +} + +typedef struct { + unsigned position; + unsigned left_up; + unsigned right_down; +}scale_pixel; + + +static void __FASTCALL__ scale_table(unsigned int start_src, unsigned int start_tar, unsigned int end_src, unsigned int end_tar, scale_pixel * table) +{ + unsigned int t; + unsigned int delta_src = end_src - start_src; + unsigned int delta_tar = end_tar - start_tar; + unsigned int src = 0; + unsigned int src_step; + if (delta_src == 0 || delta_tar == 0) { + return; + } + src_step = (delta_src << 16) / delta_tar >>1; + for (t = 0; t<=delta_tar; src += (src_step << 1), t++){ + table[t].position= MIN(src >> 16, end_src - 1); + table[t].right_down = src & 0xffff; + table[t].left_up = 0x10000 - table[t].right_down; + } +} + +/* bilinear scale, similar to vobsub's code */ +static void __FASTCALL__ scale_image(int x, int y, scale_pixel* table_x, scale_pixel* table_y, spudec_handle_t * spu) +{ + int alpha[4]; + int color[4]; + unsigned int scale[4]; + int base = table_y[y].position * spu->stride + table_x[x].position; + int scaled = y * spu->scaled_stride + x; + alpha[0] = canon_alpha(spu->aimage[base]); + alpha[1] = canon_alpha(spu->aimage[base + 1]); + alpha[2] = canon_alpha(spu->aimage[base + spu->stride]); + alpha[3] = canon_alpha(spu->aimage[base + spu->stride + 1]); + color[0] = spu->image[base]; + color[1] = spu->image[base + 1]; + color[2] = spu->image[base + spu->stride]; + color[3] = spu->image[base + spu->stride + 1]; + scale[0] = (table_x[x].left_up * table_y[y].left_up >> 16) * alpha[0]; + scale[1] = (table_x[x].right_down * table_y[y].left_up >>16) * alpha[1]; + scale[2] = (table_x[x].left_up * table_y[y].right_down >> 16) * alpha[2]; + scale[3] = (table_x[x].right_down * table_y[y].right_down >> 16) * alpha[3]; + spu->scaled_image[scaled] = (color[0] * scale[0] + color[1] * scale[1] + color[2] * scale[2] + color[3] * scale[3])>>24; + spu->scaled_aimage[scaled] = (scale[0] + scale[1] + scale[2] + scale[3]) >> 16; + if (spu->scaled_aimage[scaled]){ + spu->scaled_aimage[scaled] = 256 - spu->scaled_aimage[scaled]; + if(spu->scaled_aimage[scaled] + spu->scaled_image[scaled] > 255) + spu->scaled_image[scaled] = 256 - spu->scaled_aimage[scaled]; + } +} + +void __FASTCALL__ sws_spu_image(unsigned char *d1, unsigned char *d2, int dw, int dh, int ds, + unsigned char *s1, unsigned char *s2, int sw, int sh, int ss) +{ + struct SwsContext *ctx; + static SwsFilter filter; + static int firsttime = 1; + static float oldvar; + int i; + + if (!firsttime && oldvar != spu_gaussvar) sws_freeVec(filter.lumH); + if (firsttime) { + filter.lumH = filter.lumV = + filter.chrH = filter.chrV = sws_getGaussianVec(spu_gaussvar, 3.0); + sws_normalizeVec(filter.lumH, 1.0); + firsttime = 0; + oldvar = spu_gaussvar; + } + + ctx=sws_getContext(sw, sh, pixfmt_from_fourcc(IMGFMT_Y800), dw, dh, pixfmt_from_fourcc(IMGFMT_Y800), SWS_GAUSS, &filter, NULL, NULL); + sws_scale(ctx,&s1,&ss,0,sh,&d1,&ds); + for (i=ss*sh-1; i>=0; i--) if (!s2[i]) s2[i] = 255; //else s2[i] = 1; + sws_scale(ctx,&s2,&ss,0,sh,&d2,&ds); + for (i=ds*dh-1; i>=0; i--) if (d2[i]==0) d2[i] = 1; else if (d2[i]==255) d2[i] = 0; + sws_freeContext(ctx); +} + +void __FASTCALL__ spudec_draw_scaled(any_t*me, unsigned int dxs, unsigned int dys, draw_osd_f draw_alpha,any_t*vo) +{ + spudec_handle_t *spu = (spudec_handle_t *)me; + scale_pixel *table_x; + scale_pixel *table_y; + + if (spu->start_pts <= spu->now_pts && spu->now_pts < spu->end_pts) { + + // check if only forced subtitles are requested + if( (spu->forced_subs_only) && !(spu->is_forced_sub) ){ + return; + } + + if (!(spu_aamode&16) && (spu->orig_frame_width == 0 || spu->orig_frame_height == 0 + || (spu->orig_frame_width == dxs && spu->orig_frame_height == dys))) { + if (spu->image) + { + draw_alpha(vo,dae_curr_vdecoded(),spu->start_col, spu->start_row, spu->width, spu->height, + spu->image, spu->aimage, spu->stride); + spu->spu_changed = 0; + } + } + else { + if (spu->scaled_frame_width != dxs || spu->scaled_frame_height != dys) { /* Resizing is needed */ + /* scaled_x = scalex * x / 0x100 + scaled_y = scaley * y / 0x100 + order of operations is important because of rounding. */ + unsigned int scalex = 0x100 * dxs / spu->orig_frame_width; + unsigned int scaley = 0x100 * dys / spu->orig_frame_height; + spu->scaled_start_col = spu->start_col * scalex / 0x100; + spu->scaled_start_row = spu->start_row * scaley / 0x100; + spu->scaled_width = spu->width * scalex / 0x100; + spu->scaled_height = spu->height * scaley / 0x100; + /* Kludge: draw_alpha needs width multiple of 8 */ + spu->scaled_stride = (spu->scaled_width + 7) & ~7; + if (spu->scaled_image_size < spu->scaled_stride * spu->scaled_height) { + if (spu->scaled_image) { + free(spu->scaled_image); + spu->scaled_image_size = 0; + } + spu->scaled_image = malloc(2 * spu->scaled_stride * spu->scaled_height); + if (spu->scaled_image) { + spu->scaled_image_size = spu->scaled_stride * spu->scaled_height; + spu->scaled_aimage = spu->scaled_image + spu->scaled_image_size; + } + } + if (spu->scaled_image) { + unsigned int x, y; + if (spu->scaled_width <= 1 || spu->scaled_height <= 1) { + goto nothing_to_do; + } + switch(spu_aamode&15) { + case 4: + sws_spu_image(spu->scaled_image, spu->scaled_aimage, + spu->scaled_width, spu->scaled_height, spu->scaled_stride, + spu->image, spu->aimage, spu->width, spu->height, spu->stride); + break; + case 3: + table_x = calloc(spu->scaled_width, sizeof(scale_pixel)); + table_y = calloc(spu->scaled_height, sizeof(scale_pixel)); + if (!table_x || !table_y) { + MSG_FATAL("Fatal: spudec_draw_scaled: calloc failed\n"); + } + scale_table(0, 0, spu->width - 1, spu->scaled_width - 1, table_x); + scale_table(0, 0, spu->height - 1, spu->scaled_height - 1, table_y); + for (y = 0; y < spu->scaled_height; y++) + for (x = 0; x < spu->scaled_width; x++) + scale_image(x, y, table_x, table_y, spu); + free(table_x); + free(table_y); + break; + case 0: + /* no antialiasing */ + for (y = 0; y < spu->scaled_height; ++y) { + int unscaled_y = y * 0x100 / scaley; + int strides = spu->stride * unscaled_y; + int scaled_strides = spu->scaled_stride * y; + for (x = 0; x < spu->scaled_width; ++x) { + int unscaled_x = x * 0x100 / scalex; + spu->scaled_image[scaled_strides + x] = spu->image[strides + unscaled_x]; + spu->scaled_aimage[scaled_strides + x] = spu->aimage[strides + unscaled_x]; + } + } + break; + case 1: + { + /* Intermediate antialiasing. */ + for (y = 0; y < spu->scaled_height; ++y) { + const unsigned int unscaled_top = y * spu->orig_frame_height / dys; + unsigned int unscaled_bottom = (y + 1) * spu->orig_frame_height / dys; + if (unscaled_bottom >= spu->height) + unscaled_bottom = spu->height - 1; + for (x = 0; x < spu->scaled_width; ++x) { + const unsigned int unscaled_left = x * spu->orig_frame_width / dxs; + unsigned int unscaled_right = (x + 1) * spu->orig_frame_width / dxs; + unsigned int color = 0; + unsigned int alpha = 0; + unsigned int walkx, walky; + unsigned int base, tmp; + if (unscaled_right >= spu->width) + unscaled_right = spu->width - 1; + for (walky = unscaled_top; walky <= unscaled_bottom; ++walky) + for (walkx = unscaled_left; walkx <= unscaled_right; ++walkx) { + base = walky * spu->stride + walkx; + tmp = canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + base = y * spu->scaled_stride + x; + spu->scaled_image[base] = alpha ? color / alpha : 0; + spu->scaled_aimage[base] = + alpha * (1 + unscaled_bottom - unscaled_top) * (1 + unscaled_right - unscaled_left); + /* spu->scaled_aimage[base] = + alpha * dxs * dys / spu->orig_frame_width / spu->orig_frame_height; */ + if (spu->scaled_aimage[base]) { + spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255) + spu->scaled_image[base] = 256 - spu->scaled_aimage[base]; + } + } + } + } + break; + case 2: + { + /* Best antialiasing. Very slow. */ + /* Any pixel (x, y) represents pixels from the original + rectangular region comprised between the columns + unscaled_y and unscaled_y + 0x100 / scaley and the rows + unscaled_x and unscaled_x + 0x100 / scalex + + The original rectangular region that the scaled pixel + represents is cut in 9 rectangular areas like this: + + +---+-----------------+---+ + | 1 | 2 | 3 | + +---+-----------------+---+ + | | | | + | 4 | 5 | 6 | + | | | | + +---+-----------------+---+ + | 7 | 8 | 9 | + +---+-----------------+---+ + + The width of the left column is at most one pixel and + it is never null and its right column is at a pixel + boundary. The height of the top row is at most one + pixel it is never null and its bottom row is at a + pixel boundary. The width and height of region 5 are + integral values. The width of the right column is + what remains and is less than one pixel. The height + of the bottom row is what remains and is less than + one pixel. + + The row above 1, 2, 3 is unscaled_y. The row between + 1, 2, 3 and 4, 5, 6 is top_low_row. The row between 4, + 5, 6 and 7, 8, 9 is (unsigned int)unscaled_y_bottom. + The row beneath 7, 8, 9 is unscaled_y_bottom. + + The column left of 1, 4, 7 is unscaled_x. The column + between 1, 4, 7 and 2, 5, 8 is left_right_column. The + column between 2, 5, 8 and 3, 6, 9 is (unsigned + int)unscaled_x_right. The column right of 3, 6, 9 is + unscaled_x_right. */ + const double inv_scalex = (double) 0x100 / scalex; + const double inv_scaley = (double) 0x100 / scaley; + for (y = 0; y < spu->scaled_height; ++y) { + const double unscaled_y = y * inv_scaley; + const double unscaled_y_bottom = unscaled_y + inv_scaley; + const unsigned int top_low_row = MIN(unscaled_y_bottom, unscaled_y + 1.0); + const double top = top_low_row - unscaled_y; + const unsigned int height = unscaled_y_bottom > top_low_row + ? (unsigned int) unscaled_y_bottom - top_low_row + : 0; + const double bottom = unscaled_y_bottom > top_low_row + ? unscaled_y_bottom - floor(unscaled_y_bottom) + : 0.0; + for (x = 0; x < spu->scaled_width; ++x) { + const double unscaled_x = x * inv_scalex; + const double unscaled_x_right = unscaled_x + inv_scalex; + const unsigned int left_right_column = MIN(unscaled_x_right, unscaled_x + 1.0); + const double left = left_right_column - unscaled_x; + const unsigned int width = unscaled_x_right > left_right_column + ? (unsigned int) unscaled_x_right - left_right_column + : 0; + const double right = unscaled_x_right > left_right_column + ? unscaled_x_right - floor(unscaled_x_right) + : 0.0; + double color = 0.0; + double alpha = 0.0; + double tmp; + unsigned int base; + /* Now use these informations to compute a good alpha, + and lightness. The sum is on each of the 9 + region's surface and alpha and lightness. + + transformed alpha = sum(surface * alpha) / sum(surface) + transformed color = sum(surface * alpha * color) / sum(surface * alpha) + */ + /* 1: top left part */ + base = spu->stride * (unsigned int) unscaled_y; + tmp = left * top * canon_alpha(spu->aimage[base + (unsigned int) unscaled_x]); + alpha += tmp; + color += tmp * spu->image[base + (unsigned int) unscaled_x]; + /* 2: top center part */ + if (width > 0) { + unsigned int walkx; + for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) { + base = spu->stride * (unsigned int) unscaled_y + walkx; + tmp = /* 1.0 * */ top * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + } + /* 3: top right part */ + if (right > 0.0) { + base = spu->stride * (unsigned int) unscaled_y + (unsigned int) unscaled_x_right; + tmp = right * top * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + /* 4: center left part */ + if (height > 0) { + unsigned int walky; + for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) { + base = spu->stride * walky + (unsigned int) unscaled_x; + tmp = left /* * 1.0 */ * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + } + /* 5: center part */ + if (width > 0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) { + unsigned int walkx; + base = spu->stride * walky; + for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) { + tmp = /* 1.0 * 1.0 * */ canon_alpha(spu->aimage[base + walkx]); + alpha += tmp; + color += tmp * spu->image[base + walkx]; + } + } + } + /* 6: center right part */ + if (right > 0.0 && height > 0) { + unsigned int walky; + for (walky = top_low_row; walky < (unsigned int) unscaled_y_bottom; ++walky) { + base = spu->stride * walky + (unsigned int) unscaled_x_right; + tmp = right /* * 1.0 */ * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + } + /* 7: bottom left part */ + if (bottom > 0.0) { + base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x; + tmp = left * bottom * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + /* 8: bottom center part */ + if (width > 0 && bottom > 0.0) { + unsigned int walkx; + base = spu->stride * (unsigned int) unscaled_y_bottom; + for (walkx = left_right_column; walkx < (unsigned int) unscaled_x_right; ++walkx) { + tmp = /* 1.0 * */ bottom * canon_alpha(spu->aimage[base + walkx]); + alpha += tmp; + color += tmp * spu->image[base + walkx]; + } + } + /* 9: bottom right part */ + if (right > 0.0 && bottom > 0.0) { + base = spu->stride * (unsigned int) unscaled_y_bottom + (unsigned int) unscaled_x_right; + tmp = right * bottom * canon_alpha(spu->aimage[base]); + alpha += tmp; + color += tmp * spu->image[base]; + } + /* Finally mix these transparency and brightness information suitably */ + base = spu->scaled_stride * y + x; + spu->scaled_image[base] = alpha > 0 ? color / alpha : 0; + spu->scaled_aimage[base] = alpha * scalex * scaley / 0x10000; + if (spu->scaled_aimage[base]) { + spu->scaled_aimage[base] = 256 - spu->scaled_aimage[base]; + if (spu->scaled_aimage[base] + spu->scaled_image[base] > 255) + spu->scaled_image[base] = 256 - spu->scaled_aimage[base]; + } + } + } + } + } +nothing_to_do: + /* Kludge: draw_alpha needs width multiple of 8. */ + if (spu->scaled_width < spu->scaled_stride) + for (y = 0; y < spu->scaled_height; ++y) { + memset(spu->scaled_aimage + y * spu->scaled_stride + spu->scaled_width, 0, + spu->scaled_stride - spu->scaled_width); + } + spu->scaled_frame_width = dxs; + spu->scaled_frame_height = dys; + } + } + if (spu->scaled_image){ + switch (spu_alignment) { + case 0: + spu->scaled_start_row = dys*sub_data.pos/100; + if (spu->scaled_start_row + spu->scaled_height > dys) + spu->scaled_start_row = dys - spu->scaled_height; + break; + case 1: + spu->scaled_start_row = dys*sub_data.pos/100 - spu->scaled_height/2; + if (sub_data.pos < 50) { + if ((int)(spu->scaled_start_row) < 0) spu->scaled_start_row = 0; + } else { + if (spu->scaled_start_row + spu->scaled_height > dys) + spu->scaled_start_row = dys - spu->scaled_height; + } + break; + case 2: + spu->scaled_start_row = dys*sub_data.pos/100 - spu->scaled_height; + if ((int)(spu->scaled_start_row) < 0) spu->scaled_start_row = 0; + break; + } + draw_alpha(vo,dae_curr_vdecoded(),spu->scaled_start_col, spu->scaled_start_row, spu->scaled_width, spu->scaled_height, + spu->scaled_image, spu->scaled_aimage, spu->scaled_stride); + spu->spu_changed = 0; + } + } + } + else + { + MSG_DBG2("SPU not displayed: start_pts=%d end_pts=%d now_pts=%d\n", + spu->start_pts, spu->end_pts, spu->now_pts); + } +} + +void __FASTCALL__ spudec_update_palette(any_t* this,const unsigned int *palette) +{ + spudec_handle_t *spu = (spudec_handle_t *) this; + if (spu && palette) { + memcpy(spu->global_palette, palette, sizeof(spu->global_palette)); +// if(spu->hw_spu) +// spu->hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette); + } +} + +void __FASTCALL__ spudec_set_font_factor(any_t*this, double factor) +{ + spudec_handle_t *spu = (spudec_handle_t *) this; + spu->font_start_level = (int)(0xF0-(0xE0*factor)); +} + +any_t* __FASTCALL__ spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height) +{ + return spudec_new_scaled_vobsub(palette, NULL, 0, frame_width, frame_height); +} + +/* get palette custom color, width, height from .idx file */ +any_t* __FASTCALL__ spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsigned int custom, unsigned int frame_width, unsigned int frame_height) +{ + spudec_handle_t *this = calloc(1, sizeof(spudec_handle_t)); + if (this){ + //(fprintf(stderr,"VobSub Custom Palette: %d,%d,%d,%d", this->cuspal[0], this->cuspal[1], this->cuspal[2],this->cuspal[3]); + this->packet = NULL; + this->image = NULL; + this->scaled_image = NULL; + /* XXX Although the video frame is some size, the SPU frame is + always maximum size i.e. 720 wide and 576 or 480 high */ + this->orig_frame_width = 720; + this->orig_frame_height = (frame_height == 480 || frame_height == 240) ? 480 : 576; + this->custom = custom; + // set up palette: + this->auto_palette = 1; + if (palette){ + memcpy(this->global_palette, palette, sizeof(this->global_palette)); + this->auto_palette = 0; + } + this->custom = custom; + if (custom && cuspal) { + memcpy(this->cuspal, cuspal, sizeof(this->cuspal)); + this->auto_palette = 0; + } + // forced subtitles default: show all subtitles + this->forced_subs_only=0; + this->is_forced_sub=0; + } + else + MSG_FATAL("FATAL: spudec_init: calloc"); + return this; +} + +any_t* __FASTCALL__ spudec_new(unsigned int *palette) +{ + return spudec_new_scaled(palette, 0, 0); +} + +void __FASTCALL__ spudec_free(any_t*this) +{ + spudec_handle_t *spu = (spudec_handle_t*)this; + if (spu) { + while (spu->queue_head) + spudec_free_packet(spudec_dequeue_packet(spu)); + if (spu->packet) + free(spu->packet); + if (spu->scaled_image) + free(spu->scaled_image); + if (spu->image) + free(spu->image); + free(spu); + } +} + +void __FASTCALL__ spudec_set_hw_spu(any_t*this, vo_functions_t *hw_spu) +{ + spudec_handle_t *spu = (spudec_handle_t*)this; + if (!spu) + return; + spu->hw_spu = hw_spu; +// hw_spu->control(VOCTRL_SET_SPU_PALETTE,spu->global_palette); +} Copied: mplayerxp/libmpsub/spudec.h (from rev 192, mplayerxp/spudec.h) =================================================================== --- mplayerxp/libmpsub/spudec.h (rev 0) +++ mplayerxp/libmpsub/spudec.h 2012-10-25 06:26:33 UTC (rev 197) @@ -0,0 +1,30 @@ +#ifndef _MPLAYER_SPUDEC_H +#define _MPLAYER_SPUDEC_H + +#include "libvo/video_out.h" +#include "libvo/sub.h" + +extern int spu_alignment; +extern int spu_aamode; +extern float spu_gaussvar; + +void __FASTCALL__ spudec_heartbeat(any_t*_this, unsigned int pts100); +void __FASTCALL__ spudec_now_pts(any_t*_this, unsigned int pts100); +void __FASTCALL__ spudec_assemble(any_t*_this, unsigned char *packet, unsigned int len, unsigned int pts100); +void __FASTCALL__ spudec_draw(any_t*this, draw_osd_f draw_alpha,any_t* vo); +void __FASTCALL__ spudec_draw_scaled(any_t*_this, unsigned int dxs, unsigned int dys,draw_osd_f draw_alpha,any_t* vo); +void __FASTCALL__ spudec_update_palette(any_t*_this,const unsigned int *palette); +any_t* __FASTCALL__ spudec_new_scaled(unsigned int *palette, unsigned int frame_width, unsigned int frame_height); +any_t* __FASTCALL__ spudec_new_scaled_vobsub(unsigned int *palette, unsigned int *cuspal, unsigned int custom, unsigned int frame_width, unsigned int frame_height); +any_t* __FASTCALL__ spudec_new(unsigned int *palette); +void __FASTCALL__ spudec_free(any_t*_this); +void __FASTCALL__ spudec_reset(any_t*_this); // called after seek +int __FASTCALL__ spudec_visible(any_t*_this); // check if spu is visible +void __FASTCALL__ spudec_set_font_factor(any_t*_this, double factor); // sets the equivalent to ffactor +void __FASTCALL__ spudec_set_hw_spu(any_t*_this, vo_functions_t *hw_spu); +int __FASTCALL__ spudec_changed(any_t*_this); +void __FASTCALL__ spudec_calc_bbox(any_t*me, unsigned int dxs, unsigned int dys, unsigned int* bbox); +void __FASTCALL__ spudec_set_forced_subs_only(any_t* const _this, const unsigned int flag); + +#endif + Copied: mplayerxp/libmpsub/subreader.c (from rev 184, mplayerxp/subreader.c) =================================================================== --- mplayerxp/libmpsub/subreader.c (rev 0) +++ mplayerxp/libmpsub/subreader.c 2012-10-25 06:26:33 UTC (rev 197) @@ -0,0 +1,886 @@ +/* + * Subtitle reader with format autodetection + * + * Written by laaz + * Some code cleanup & realloc() by A'rpi/ESP-team + * dunnowhat sub format by szabi + */ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "mp_config.h" +#include "subreader.h" +#include "libvo/sub.h" + +#define ERR ((any_t*) -1) + +#ifdef USE_ICONV +#ifdef HAVE_GICONV +#include <giconv.h> +#else +#include <iconv.h> +#endif +#endif +#define MSGT_CLASS MSGT_SUBREADER +#include "__mp_msg.h" + +/* Maximal length of line of a subtitle */ +#define LINE_LEN 1000 + +static float mpsub_position=0; + +int sub_uses_time=0; +int sub_errs=0; +int sub_num=0; // number of subtitle structs +int sub_slacktime=2000; // 20 seconds + +/* Use the SUB_* constant defined in the header file */ +int sub_format=SUB_INVALID; + +static int __FASTCALL__ eol(char p) { + return (p=='\r' || p=='\n' || p=='\0'); +} + +/* Remove leading and trailing space */ +static void __FASTCALL__ trail_space(char *s) { + int i = 0; + while (isspace(s[i])) ++i; + if (i) strcpy(s, s + i); + i = strlen(s) - 1; + while (i > 0 && isspace(s[i])) s[i--] = '\0'; +} + + +static subtitle * __FASTCALL__ sub_read_line_sami(FILE *fd, subtitle *current) { + static char line[LINE_LEN+1]; + static char *s = NULL, *slacktime_s; + char text[LINE_LEN+1], *p=NULL, *q; + int state; + + current->lines = current->start = current->end = 0; + state = 0; + + /* read the first line */ + if (!s) + if (!(s = fgets(line, LINE_LEN, fd))) return 0; + + do { + switch (state) { + + case 0: /* find "START=" or "Slacktime:" */ + slacktime_s = strstr (s, "Slacktime:"); + if (slacktime_s) sub_slacktime = strtol (slacktime_s + 10, NULL, 0) / 10; + + s = strstr (s, "Start="); + if (s) { + current->start = strtol (s + 6, &s, 0) / 10; + state = 1; continue; + } + break; + + case 1: /* find "<P" */ + if ((s = strstr (s, "<P"))) { s += 2; state = 2; continue; } + break; + + case 2: /* find ">" */ + if ((s = strchr (s, '>'))) { s++; state = 3; p = text; continue; } + break; + + case 3: /* get all text until '<' appears */ + if (*s == '\0') break; + else if (!strncasecmp (s, "<br>",... [truncated message content] |