diff --git a/Makefile.dep b/Makefile.dep index fe95e18503..d8178879c9 100644 --- a/Makefile.dep +++ b/Makefile.dep @@ -29,7 +29,7 @@ default: $(dependancies): .dep/%.d: %.c @test -d .dep/$(dir $*) || mkdir -p .dep/$(dir $*) @echo "generating dependancies for $*.c" - @$(SHELL) -ec '$(CC) $(DCFLAGS) $(CFLAGS) $< \ + @$(SHELL) -ec '$(CC) $(DCFLAGS) $(CFLAGS) $(DEFINE) $< \ | sed '\''s/$(subst .,\.,$(notdir $*))\.o[ :]*/$(subst /,\/,$*).o \ .dep\/$(subst /,\/,$*).d : /g'\'' > $@; \ [ -s $@ ] || rm -f $@' diff --git a/Makefile.in b/Makefile.in index d1320bf5a1..75e488a045 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,4 +1,5 @@ # Generated automatically from Makefile.in by configure. +# Generated automatically from Makefile.in by configure. ################################################################################ # vlc (VideoLAN Client) main makefile # (c)1998 VideoLAN @@ -19,7 +20,7 @@ AOUT += dsp AOUT += dummy # Video output settings -VOUT += x11 +#VOUT += x11 #VOUT += fb #VOUT += ggi #VOUT += glide @@ -68,8 +69,8 @@ DEBUG=0 #----------------- do not change anything below this line ---------------------- -prefix=@prefix@ -INSTALL=@INSTALL@ +prefix=/usr/local +INSTALL=/bin/install -c ################################################################################ # Configuration pre-processing @@ -127,11 +128,11 @@ ifeq ($(SYS),LINUX) LIB += -lpthread -ldl endif -ifeq ($SYS),BEOS) -LIB += -llibroot -llibgame -llibbe -endif - +ifeq ($(SYS),BEOS) +LIB += -lbe -lroot -lgame +else LIB += -lm +endif # # C compiler flags: compilation @@ -141,6 +142,9 @@ CCFLAGS += -Wall CCFLAGS += -D_REENTRANT CCFLAGS += -D_GNU_SOURCE +# flags needed for clean beos compilation +CCFLAGS += -Wno-multichar -Wno-ctor-dtor-privacy -Woverloaded-virtual + # Optimizations : don't compile debug versions with them CCFLAGS += -O6 CCFLAGS += -ffast-math -funroll-loops -fargument-noalias-global @@ -192,7 +196,7 @@ LCFLAGS += -Wall # Debugging support ifeq ($(DEBUG),1) CFLAGS += -g -#CFLAGS += -pg +CFLAGS += -pg endif ################################################################################# @@ -276,6 +280,7 @@ misc_obj = misc/mtime.o \ misc/plugins.o \ misc/decoder_fifo.o + C_OBJ = $(interface_obj) \ $(input_obj) \ $(audio_output_obj) \ @@ -289,6 +294,10 @@ C_OBJ = $(interface_obj) \ $(vlan_obj) \ $(misc_obj) +ifeq ($(SYS), BEOS) +CPP_OBJ = misc/beos_specific.o +endif + # # Assembler Objects # @@ -317,9 +326,10 @@ PLUGIN_OBJ = $(intf_plugin) $(aout_plugin) $(vout_plugin) # Other lists of files # C_OBJ := $(C_OBJ:%.o=src/%.o) +CPP_OBJ := $(CPP_OBJ:%.o=src/%.o) ASM_OBJ := $(ASM_OBJ:%.o=src/%.o) -sources := $(C_OBJ:%.o=%.c) $(PLUGIN_OBJ:%.so=%.c) -dependancies := $(sources:%.c=.dep/%.d) +sources_c := $(C_OBJ:%.o=%.c) +dependancies := $(sources_c:%.c=.dep/%.d) # All symbols must be exported export @@ -331,10 +341,10 @@ export # # Virtual targets # -all: vlc +all: vlc plugins clean: - rm -f $(C_OBJ) $(ASM_OBJ) $(PLUGIN_OBJ) + rm -f $(C_OBJ) $(CPP_OBJ) $(ASM_OBJ) $(PLUGIN_OBJ) distclean: clean rm -f **/*.o **/*.so **/*~ *.log @@ -376,8 +386,15 @@ FORCE: # # Real targets # -vlc: $(C_OBJ) $(ASM_OBJ) $(PLUGIN_OBJ) - $(CC) $(CCFLAGS) $(LCFLAGS) $(CFLAGS) --export-dynamic -rdynamic -o $@ $(C_OBJ) $(ASM_OBJ) +vlc: $(C_OBJ) $(CPP_OBJ) $(ASM_OBJ) +ifeq ($(SYS), BEOS) + $(CC) $(CCFLAGS) $(LCFLAGS) $(CFLAGS) -Xlinker -soname=_APP_ -o $@ $(C_OBJ) $(CPP_OBJ) $(ASM_OBJ) +# ln -s ../vlc ./plugins/_APP_ +else + $(CC) $(CCFLAGS) $(LCFLAGS) $(CFLAGS) --export-dynamic -rdynamic -o $@ $(C_OBJ) $(CPP_OBJ) $(ASM_OBJ) +endif + +plugins: $(PLUGIN_OBJ) # # Generic rules (see below) @@ -391,19 +408,23 @@ $(C_OBJ): %.o: %.c @echo "compiling $*.o from $*.c" @$(CC) $(CCFLAGS) $(CFLAGS) -c -o $@ $< +$(CPP_OBJ): %.o: %.cpp + @echo "compiling $*.o from $*.cpp" + @$(CC) $(CCFLAGS) $(CFLAGS) -c -o $@ $< + $(ASM_OBJ): %.o: Makefile.dep $(ASM_OBJ): %.o: %.S @echo "assembling $*.o from $*.S" @$(CC) $(CFLAGS) -c -o $@ $< -$(PLUGIN_OBJ): %.so: Makefile.dep -$(PLUGIN_OBJ): %.so: .dep/%.d +#$(PLUGIN_OBJ): %.so: Makefile.dep +#$(PLUGIN_OBJ): %.so: .dep/%.d # audio plugins plugins/aout/aout_dummy.so plugins/aout/aout_dsp.so: %.so: %.c @echo "compiling $*.so from $*.c" ifeq ($(SYS), BEOS) - @$(CC) $(CCFLAGS) $(CFLAGS) -nostart -o $@ $< + @$(CC) $(CCFLAGS) $(CFLAGS) -nostart -Xlinker -soname=$@ -o $@ $< plugins/_APP_ else @$(CC) $(CCFLAGS) $(CFLAGS) -shared -o $@ $< endif @@ -421,7 +442,7 @@ plugins/intf/intf_dummy.so plugins/vout/vout_dummy.so \ plugins/intf/intf_fb.so plugins/vout/vout_fb.so: %.so: %.c @echo "compiling $*.so from $*.c" ifeq ($(SYS), BEOS) - @$(CC) $(CCFLAGS) $(CFLAGS) -nostart -o $@ $< + @$(CC) $(CCFLAGS) $(CFLAGS) -nostart -Xlinker -soname=$@ -o $@ $< plugins/_APP_ else @$(CC) $(CCFLAGS) $(CFLAGS) -shared -o $@ $< endif @@ -446,6 +467,14 @@ plugins/intf/intf_ggi.so plugins/vout/vout_ggi.so: %.so: %.c @echo "compiling $*.so from $*.c" @$(CC) $(CCFLAGS) $(CFLAGS) -lggi -shared -o $@ $< +plugins/intf/intf_beos.so: %.so: %.cpp + @echo "compiling $*.so from $*.cpp" + @$(CC) $(LCFLAGS) $(CCFLAGS) $(CFLAGS) -nostart -Xlinker -soname=$@ -o $@ $< plugins/_APP_ + +plugins/vout/vout_beos.so: %.so: %.cpp + @echo "compiling $*.so from $*.cpp" + @$(CC) $(LCFLAGS) $(CCFLAGS) $(CFLAGS) -nostart -Xlinker -soname=$@ -o $@ $< plugins/_APP_ + ################################################################################ # Note on generic rules and dependancies diff --git a/include/beos_specific.h b/include/beos_specific.h new file mode 100644 index 0000000000..3036c09613 --- /dev/null +++ b/include/beos_specific.h @@ -0,0 +1,39 @@ +/***************************************************************************** + * beos_init.h: Initialization for BeOS specific features + ***************************************************************************** + * Copyright (C) 1999, 2000 VideoLAN + * + * 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 + * 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-1307, USA. + *****************************************************************************/ + +/***************************************************************************** + * Prototypes + *****************************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +void beos_Init( void ); +void beos_Clean( void ); +char * beos_GetProgramPath( void ); + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/include/beos_window.h b/include/beos_window.h new file mode 100644 index 0000000000..157ec29490 --- /dev/null +++ b/include/beos_window.h @@ -0,0 +1,80 @@ +/***************************************************************************** + * beos_window.h: beos window class prototype + ***************************************************************************** + * Copyright (C) 1999, 2000 VideoLAN + * + * 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 + * 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-1307, USA. + *****************************************************************************/ + +class VideoWindow : public BDirectWindow +{ +public: + // standard constructor and destructor + VideoWindow(BRect frame, const char *name, vout_thread_t *p_video_output); + ~VideoWindow(); + + // standard window member + virtual bool QuitRequested(); + virtual void MessageReceived(BMessage *message); + + // this is the hook controling direct screen connection + virtual void DirectConnected(direct_buffer_info *info); + + int32 i_bytes_per_pixel; + int32 i_screen_depth; + vout_thread_t *p_vout; + + uint8 *fBits; + int32 fRowBytes; + color_space fFormat; + clipping_rect fBounds; + + uint32 fNumClipRects; + clipping_rect *fClipList; + + bool fDirty; + bool fReady; + bool fConnected; + bool fConnectionDisabled; + BLocker *locker; + thread_id fDrawThreadID; +}; + +class InterfaceWindow : public BWindow +{ +public: + InterfaceWindow( BRect frame, const char *name, intf_thread_t *p_intf ); + ~InterfaceWindow(); + + // standard window member + virtual bool QuitRequested(); + virtual void MessageReceived(BMessage *message); + + intf_thread_t *p_interface; +}; + +class InterfaceView : public BView +{ +public: + InterfaceView(); + ~InterfaceView(); + + virtual void MessageReceived(BMessage *message); + +}; \ No newline at end of file diff --git a/include/common.h b/include/common.h index e9e105df42..8b37b1f7ec 100644 --- a/include/common.h +++ b/include/common.h @@ -103,12 +103,14 @@ typedef struct video_parser_s * p_video_parser_t; #define PAD(n, d) ( ((n) % (d)) ? ((((n) / (d)) + 1) * (d)) : (n) ) /* MAX and MIN: self explanatory */ +//#ifndef SYS_BEOS #ifndef MAX #define MAX(a, b) ( ((a) > (b)) ? (a) : (b) ) #endif #ifndef MIN #define MIN(a, b) ( ((a) < (b)) ? (a) : (b) ) #endif +//#endif /* MSB (big endian)/LSB (little endian) convertions - network order is always * MSB, and should be used for both network communications and files. Note that diff --git a/include/threads.h b/include/threads.h index 0a295e0506..c1822dc33b 100644 --- a/include/threads.h +++ b/include/threads.h @@ -23,6 +23,8 @@ * Boston, MA 02111-1307, USA. *****************************************************************************/ +#include + #if defined(HAVE_PTHREAD_H) /* pthreads (Linux & BSD for example) */ #include @@ -30,9 +32,10 @@ #include #elif defined(HAVE_KERNEL_SCHEDULER_H) && defined(HAVE_KERNEL_OS_H) /* BeOS */ +#undef MAX +#undef MIN #include #include - #else #error no threads available on your system ! #endif @@ -228,12 +231,11 @@ static __inline__ int vlc_mutex_init( vlc_mutex_t *p_mutex ) return 0; #elif defined(HAVE_KERNEL_SCHEDULER_H) && defined(HAVE_KERNEL_OS_H) +/* // check the arguments and whether it's already been initialized - if( !p_mutex ) - return B_BAD_VALUE; - - if( p_mutex->init == 9999 ) - return EALREADY; + if( !p_mutex ) return B_BAD_VALUE; + if( p_mutex->init == 9999 ) return EALREADY; +*/ p_mutex->lock = create_sem( 1, "BeMutex" ); p_mutex->owner = -1; @@ -257,18 +259,16 @@ static __inline__ int vlc_mutex_lock( vlc_mutex_t *p_mutex ) #elif defined(HAVE_KERNEL_SCHEDULER_H) && defined(HAVE_KERNEL_OS_H) status_t err; - - if( !p_mutex ) - return B_BAD_VALUE; - - if( p_mutex->init < 2000 ) - return B_NO_INIT; +/* + if( !p_mutex ) return B_BAD_VALUE; + if( p_mutex->init < 2000 ) return B_NO_INIT; lazy_init_mutex( p_mutex ); - +*/ err = acquire_sem( p_mutex->lock ); - if( !err ) - p_mutex->owner = find_thread( NULL ); +/* + if( !err ) p_mutex->owner = find_thread( NULL ); +*/ return err; @@ -288,11 +288,9 @@ static __inline__ int vlc_mutex_unlock( vlc_mutex_t *p_mutex ) return 0; #elif defined(HAVE_KERNEL_SCHEDULER_H) && defined(HAVE_KERNEL_OS_H) - if(! p_mutex) - return B_BAD_VALUE; - - if( p_mutex->init < 2000 ) - return B_NO_INIT; +/* + if(! p_mutex) return B_BAD_VALUE; + if( p_mutex->init < 2000 ) return B_NO_INIT; lazy_init_mutex( p_mutex ); @@ -300,6 +298,7 @@ static __inline__ int vlc_mutex_unlock( vlc_mutex_t *p_mutex ) return ENOLCK; p_mutex->owner = -1; +*/ release_sem( p_mutex->lock ); return B_OK; diff --git a/src/audio_output/audio_output.c b/src/audio_output/audio_output.c index 68884dbe71..8a349aa518 100644 --- a/src/audio_output/audio_output.c +++ b/src/audio_output/audio_output.c @@ -95,7 +95,6 @@ aout_thread_t *aout_CreateThread( int *pi_status ) /* Request an interface plugin */ psz_method = main_GetPszVariable( AOUT_METHOD_VAR, AOUT_DEFAULT_METHOD ); - if( RequestPlugin( &p_aout->aout_plugin, "aout", psz_method ) ) { intf_ErrMsg( "error: could not open audio plugin aout_%s.so\n", psz_method ); diff --git a/src/input/input_file.c b/src/input/input_file.c index f6da4561d1..9dd172e429 100644 --- a/src/input/input_file.c +++ b/src/input/input_file.c @@ -26,24 +26,940 @@ *****************************************************************************/ #include "defs.h" +#include #include /* on BSD, uio.h needs types.h */ #include /* "input.h" */ +#include /* fstat, off_t ... */ +#include /* ntohl ... */ +#include /* malloc, read ... */ +#include + #include "config.h" #include "common.h" #include "threads.h" #include "mtime.h" +#include "intf_msg.h" #include "input.h" #include "input_file.h" +#define BUF_SIZE (797*3) + +#define PS_METHOD 1 +#define TS_METHOD 2 + +#define TS_PACKET_SIZE 188 +#define TS_IN_UDP 7 + +#define PS_BUFFER_SIZE 16384 +#define NO_PES 0 +#define AUDIO_PES 1 +#define VIDEO_PES 2 +#define AC3_PES 3 +#define SUBTITLE_PES 4 +#define PRIVATE_PES 5 +#define UNKNOWN_PES 12 + +#define PCR_PID 0x20 /* 0x20 == first video stream + * 0x40 == first audio stream */ + +typedef u8 file_ts_packet[TS_PACKET_SIZE]; +typedef file_ts_packet udp_packet[TS_IN_UDP]; + +typedef struct synchro_struct +{ + mtime_t delta_clock; + mtime_t slope; + mtime_t last_pcr_time; + + file_ts_packet *last_pcr; +} synchro_t; + +typedef struct in_data_s +{ + int start, end; + vlc_mutex_t lock; + vlc_cond_t notfull; + vlc_cond_t notempty; + udp_packet buf[BUF_SIZE+1]; +} in_data_t; + +typedef struct own_pcr_s +{ + int start, end; + vlc_mutex_t lock; + file_ts_packet *buf[(BUF_SIZE+1)*TS_IN_UDP+1]; +} own_pcr_t; + +typedef struct options_s +{ + unsigned int pcr_pid; + u8 i_file_type; + int in; +} options_t; + +typedef struct s_ps +{ + unsigned int pat_counter; + unsigned int pmt_counter; + /* + * 16 audio mpeg streams + * 16 audio AV3 streams + * 16 video mpeg streams + * 32 subtitle streams + */ + unsigned int media_counter[0x100]; + unsigned int association_table[0x100]; + unsigned int found_streams; + + unsigned int found_pts; + + unsigned int ts_to_write; + unsigned int ts_written; + unsigned int sent_ts; + + unsigned char *ps_data; + unsigned char *ps_end; + unsigned char *ps_buffer; + + unsigned int pes_id; + unsigned int private_id; + unsigned int has_pts; + unsigned int pcr_pid; + + unsigned int pes_type; + unsigned int pes_size; + unsigned int to_skip; + unsigned int offset; +} ps_t; + +typedef struct input_file_s +{ + boolean_t b_die; /* b_die flag for the disk thread */ + vlc_thread_t disk_thread; + + synchro_t synchro; + ps_t ps; + in_data_t in_data; + options_t options; + own_pcr_t own_pcr; +} input_file_t; + +/* local prototypes */ +void ps_fill( input_file_t * p_if, boolean_t wait ); +ssize_t safe_read(int fd, unsigned char *buf, int count); +void input_DiskThread( input_file_t * p_if ); +int init_synchro( input_file_t * p_if ); + +input_file_t input_file; + +/****************************************************************************** + * ConvertPCRTime : extracts and converts the PCR time in microseconds + ******************************************************************************/ + +s64 ConvertPCRTime(file_ts_packet *pcr_buff) +{ + return( (((((s64)U32_AT(((u8*)pcr_buff)+6)) << 1) | (((u8*)pcr_buff)[10] >> 7)) * 300) / 27 ); +} + +/****************************************************************************** + * wait_a_moment : Compute how long we must wait before sending a TS packet + ******************************************************************************/ + +static void wait_a_moment( input_file_t * p_if, file_ts_packet *ts) +{ + synchro_t * p_synchro = &input_file.synchro; + + static int retard_count = 0; + static s64 wait_max = 0; + s64 sendtime; /* the date at which the TS packet should be sent */ + s64 wait; + + sendtime = p_synchro->last_pcr_time + p_synchro->delta_clock + + p_synchro->slope * ((ts - p_synchro->last_pcr + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP)); + wait = sendtime - mdate(); + //fprintf(stderr,"last PCR Time : %Ld\n", p_synchro->last_pcr_time ); + if( wait > 0 ) + { + retard_count = 0; + if(wait > 100000) + { + fprintf( stderr, "Warning : wait time may be too long : %Ld\n", wait ); + return; + } + msleep( wait ); + } + else + { + if( wait < wait_max ) + { + wait_max = wait; + } + retard_count++; + if( retard_count == 16 ) + { + retard_count = 0; + //fprintf( stderr, "delay : %Ldms, max delay : %Ldms\n", -wait/1000, -wait_max/1000 ); + fflush(stdout); + } + } +} + +/****************************************************************************** + * adjust : Adjust the encoder clock & remove the PCR from own_pcr + ******************************************************************************/ + +static void adjust( input_file_t * p_if, file_ts_packet *ts ) +{ + synchro_t * p_synchro = &p_if->synchro; + own_pcr_t * p_own_pcr = &p_if->own_pcr; + file_ts_packet *next_pcr; + int no_discontinuity = 1; + + if( ((u8*)ts)[5] & 0x80 ) + { + /* There is a discontinuity - I recalculate the delta */ + p_synchro->delta_clock = mdate() - ConvertPCRTime(ts); + intf_DbgMsg( "input warning: clock discontinuity\n" ); + no_discontinuity = 0; + } + else + { + p_synchro->last_pcr = ts; + p_synchro->last_pcr_time = ConvertPCRTime( ts ); + } + + vlc_mutex_lock(&p_own_pcr->lock); + p_own_pcr->start++; + p_own_pcr->start %= (BUF_SIZE+1)*TS_IN_UDP+1; + + /* If we have 2 consecutiv PCR, we can reevaluate slope */ + if( (p_own_pcr->start != p_own_pcr->end) && + no_discontinuity && + !((((u8*) next_pcr = p_own_pcr->buf[p_own_pcr->start]))[5] & 0x80)) + { + s64 current_pcr_time = ConvertPCRTime(ts); + s64 next_pcr_time = ConvertPCRTime(next_pcr); + + if( (next_pcr_time - current_pcr_time < 0) || (next_pcr_time - current_pcr_time > 700000)) + { + fprintf( stderr, "Warning: possible discontinuity\n" ); + p_synchro->delta_clock = mdate() - next_pcr_time; + } + else + { + //fprintf(stderr,"next - current : %Ld\n", next_pcr_time - current_pcr_time); + p_synchro->slope = (next_pcr_time - current_pcr_time) / + ((next_pcr - ts + (BUF_SIZE+1)*TS_IN_UDP) % ((BUF_SIZE+1)*TS_IN_UDP)); + //fprintf(stderr,"slope : %Ld\n", p_synchro->slope); + } + } + + vlc_mutex_unlock(&p_own_pcr->lock); +} + +/****************************************************************************** + * safe_read : Buffered reading method + ******************************************************************************/ + +ssize_t safe_read(int fd, unsigned char *buf, int count) +{ + int ret, cnt=0; + + while(cnt < count) + { + ret = read(fd, buf+cnt, count-cnt); + if(ret < 0) + return ret; + if(ret == 0) + break; + cnt += ret; + } + + return cnt; +} + +/****************************************************************************** + * keep_pcr : Put a TS packet in the fifo if it owns a PCR + ******************************************************************************/ + +int keep_pcr(int pcr_pid, file_ts_packet *ts) +{ + own_pcr_t * p_own_pcr = &input_file.own_pcr; + +#define p ((u8 *)ts) + if ((p[3] & 0x20) && p[4] && (p[5] & 0x10) + && ((((p[1]<<8)+p[2]) & 0x1FFF) == pcr_pid)) + { + /* adaptation_field_control is set, adaptation_field_lenght is not 0, + * PCR_flag is set, pid == pcr_pid */ + vlc_mutex_lock(&p_own_pcr->lock); + p_own_pcr->buf[p_own_pcr->end++] = ts; + p_own_pcr->end %= (BUF_SIZE+1)*TS_IN_UDP+1; + vlc_mutex_unlock(&p_own_pcr->lock); + return 1; + } + else + return 0; +#undef p +} + +/****************************************************************************** + * get_pid : gets a pid from a PES type + ******************************************************************************/ + +int get_pid (ps_t *p_ps) +{ + int i, tofind, delta; + + switch( p_ps->pes_type ) + { + case VIDEO_PES: + delta = 0x20; + tofind = p_ps->pes_id; + break; + case AUDIO_PES: + delta = 0x40; + tofind = p_ps->pes_id; + break; + case SUBTITLE_PES: + delta = 0x60; + tofind = p_ps->private_id; + break; + case AC3_PES: + delta = 0x80; + tofind = p_ps->private_id; + break; + default: + return(-1); + } + + /* look in the table if we can find one */ + for ( i=delta; i < delta + 0x20; i++ ) + { + if ( p_ps->association_table[i] == tofind ) + return (i); + + if( !p_ps->association_table[i] ) + break; + } + + /* we must allocate a new entry */ + if (i == delta + 0x20) + return(-1); + + p_ps->association_table[i] = tofind; + p_ps->media_counter[i] = 0; + + fprintf( stderr, "allocated new PID 0x%.2x to stream ID 0x%.2x\n", i, tofind ); + + return ( i ); +} + +/****************************************************************************** + * write_media_ts : writes a ts packet from a ps stream + ******************************************************************************/ + +void write_media_ts(ps_t *ps, unsigned char *ts, unsigned int pid) +{ + int i,j; + s64 clock; + long int extclock; + + /* if offset == 0, it means we haven't examined the PS yet */ + if (ps->offset == 0) + { + if (ps->pes_size < 184) { + + //fprintf(stderr,"[WARNING: small PES]\n"); + ts[0] = 0x47; /* sync_byte */ + ts[1] = 0x40; /* payload_unit_start_indicator si début de PES */ + ts[2] = pid; + + ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f); + ts[4] = 184 - ps->pes_size - 1; + ts[5] = 0x00; + for (i=6 ; i < 188 - ps->pes_size ; i++) ts[i]=0xFF; /* facultatif ? */ + memcpy(ts + 188 - ps->pes_size, ps->ps_data, ps->pes_size); + + /* this PS is finished, next time we'll pick a new one */ + ps->pes_type = NO_PES; + ps->ps_data += ps->pes_size; + ps->offset += ps->pes_size; + //fprintf( stderr, "wrote %i final data (size was 0x%.2x)\n", ps->offset, ps->pes_size); + return; + + } + } + + /* now we still can have offset == 0, but size is initialized */ + + ts[0] = 0x47; /* sync_byte */ + ts[1] = (ps->offset == 0) ? 0x40 : 0x00; /* payload_unit_start_indicator si début de PES */ + ts[2] = pid; + + //fprintf( stderr, "checking clock for %.2x while we have %.2x\n", ps->pcr_pid, pid ); + //fprintf( stderr, "offset 0x%.2x, pts 0x%.2x, pid %i \n", ps->offset, ps->has_pts, pid ); + if ( (ps->offset == 0) && (ps->has_pts == 0xc0) && (ps->pcr_pid == pid) ) + { + + ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f); + ts[4] = 0x07; /* taille de l'adaptation field */ + ts[5] = 0x50; /* rtfm */ + + /* on va lire le PTS */ + clock = ( ((s64)(ps->ps_data[9] & 0x0E) << 29) | + (((s64)U16_AT(ps->ps_data + 10) << 14) - (1 << 14)) | + ((s64)U16_AT(ps->ps_data + 12) >> 1) ); + + //fprintf( stderr, "clock is %lli\n", clock ); + ps->has_pts = 0; + + extclock = 0x000; + ts[6] = (clock & 0x1fe000000) >> 25; /* ---111111110000000000000000000000000 */ + ts[7] = (clock & 0x001fe0000) >> 17; /* ---000000001111111100000000000000000 */ + ts[8] = (clock & 0x00001fe00) >> 9; /* ---000000000000000011111111000000000 */ + ts[9] = (clock & 0x0000001fe) >> 1; /* ---000000000000000000000000111111110 */ + + ts[10] = 0x7e + ((clock & 0x01) << 7) + ((extclock & 0x100) >> 8); + ts[11] = extclock & 0xff; + + memcpy(ts + 4 + 8, ps->ps_data, 184 - 8); + + ts[15] = 0xe0; /* FIXME : we don't know how to choose program yet */ + + ps->offset += 184 - 8; + ps->ps_data += 184 - 8; + } + else if (ps->offset <= ps->pes_size - 184) + { + + ts[3] = 0x10 + (ps->media_counter[pid] & 0x0f); + memcpy(ts + 4, ps->ps_data, 184); + + ps->offset += 184; + ps->ps_data += 184; + + } + else + { + + j = ps->pes_size - ps->offset; + ts[3] = 0x30 + (ps->media_counter[pid] & 0x0f); + ts[4] = 184 - j - 1; + ts[5] = 0x00; + for (i=6 ; i < 188 - j ; i++) ts[i]=0xFF; /* facultatif ? */ + memcpy(ts + 4 + 184 - j, ps->ps_data, j); + ps->offset += j; /* offset = size */ + ps->ps_data += j; /* offset = size */ + + /* the PES is finished */ + ps->pes_type = NO_PES; + ps->sent_ts++; + + //fprintf( stderr, "wrote 0x%.2x data (size was 0x%.2x)\n", ps->offset, ps->pes_size); + } + + //fprintf(stderr, "[PES size: %i]\n", ps->pes_size); +} + +/****************************************************************************** + * write_pat : writes a program association table + ******************************************************************************/ + +void write_pat(ps_t *ps, unsigned char *ts) +{ + int i; + + //fprintf( stderr, "wrote a PAT\n"); + + ts[0] = 0x47; /* sync_byte */ + ts[1] = 0x40; + ts[2] = 0x00; /* PID = 0x0000 */ + ts[3] = 0x10 + (ps->pat_counter & 0x0f); + ts[4] = ts[5] = 0x00; + + ts[6] = 0xb0; /* */ + ts[7] = 0x11; /* section_length = 0x011 */ + + ts[8] = 0x00; + ts[9] = 0xb0; /* TS id = 0x00b0 */ + + ts[10] = 0xc1; + /* section # and last section # */ + ts[11] = ts[12] = 0x00; + + /* Network PID (useless) */ + ts[13] = ts[14] = 0x00; ts[15] = 0xe0; ts[16] = 0x10; + + /* Program Map PID */ + ts[17] = 0x03; ts[18] = 0xe8; ts[19] = 0xe0; ts[20] = 0x64; + + /* CRC */ + ts[21] = 0x4d; ts[22] = 0x6a; ts[23] = 0x8b; ts[24] = 0x0f; + + for (i=25 ; i < 188 ; i++) ts[i]=0xFF; /* facultatif ? */ + + ps->sent_ts++; +} + +/****************************************************************************** + * write_pmt : writes a program map table + ******************************************************************************/ + +void write_pmt(ps_t *ps, unsigned char *ts) +{ + int i; + + //fprintf( stderr, "wrote a PMT\n"); + + ts[0] = 0x47; /* sync_byte */ + ts[1] = 0x40; + ts[2] = 0x0064; /* PID = 0x0064 */ + ts[3] = 0x10 + (ps->pmt_counter & 0x0f); + + ts[4] = 0x00; + ts[5] = 0x02; + + ts[6] = 0xb0; /* */ + ts[7] = 0x34; /* section_length = 0x034 */ + + ts[8] = 0x03; + ts[9] = 0xe8; /* prog number */ + + ts[10] = 0xc1; + /* section # and last section # */ + ts[11] = ts[12] = 0x00; + + /* PCR PID */ + ts[13] = 0xe0; + ts[14] = 0x20; + + /* program_info_length == 0 */ + ts[15] = 0xf0; ts[16] = 0x00; + + /* Program Map / Video PID */ + ts[17] = 0x02; /* stream type = video */ + ts[18] = 0xe0; ts[19] = 0x20; + ts[20] = 0xf0; ts[21] = 0x09; /* es info length */ + /* useless info */ + ts[22] = 0x07; ts[23] = 0x04; ts[24] = 0x08; ts[25] = 0x80; ts[26] = 0x24; + ts[27] = 0x02; ts[28] = 0x11; ts[29] = 0x01; ts[30] = 0xfe; + + /* Audio PID */ + ts[31] = 0x88; /* stream type = audio */ /* FIXME : was 0x04 */ + ts[32] = 0xe0; ts[33] = 0x40; + ts[34] = 0xf0; ts[35] = 0x00; /* es info length */ + + /* reserved PID */ +#if 0 + ts[36] = 0x82; /* stream type = private */ + ts[37] = 0xe0; ts[38] = 0x60; /* subtitles */ +#else + ts[36] = 0x81; /* stream type = private */ + ts[37] = 0xe0; ts[38] = 0x80; /* ac3 audio */ +#endif + ts[39] = 0xf0; ts[40] = 0x0f; /* es info length */ + /* useless info */ + ts[41] = 0x90; ts[42] = 0x01; ts[43] = 0x85; ts[44] = 0x89; ts[45] = 0x04; + ts[46] = 0x54; ts[47] = 0x53; ts[48] = 0x49; ts[49] = 0x00; ts[50] = 0x0f; + ts[51] = 0x04; ts[52] = 0x00; ts[53] = 0x00; ts[54] = 0x00; ts[55] = 0x10; + + /* CRC */ + ts[56] = 0x96; ts[57] = 0x70; ts[58] = 0x0b; ts[59] = 0x7c; /* for video pts */ + //ts[56] = 0xa1; ts[57] = 0x7c; ts[58] = 0xd8; ts[59] = 0xaa; /* for audio pts */ + + for (i=60 ; i < 188 ; i++) ts[i]=0xFF; /* facultatif ? */ + + ps->sent_ts++; +} + + +/****************************************************************************** + * ps_thread + ****************************************************************************** + * We use threading to allow cool non-blocking read from the disk. This + * implicit thread is the disk (producer) thread, it reads packets from + * the PS file on the disk, and stores them in a FIFO. + ******************************************************************************/ + +void ps_thread( input_file_t * p_if ) +{ + int i; + ps_t * p_ps = &p_if->ps; + own_pcr_t * p_own_pcr = &p_if->own_pcr; + in_data_t * p_in_data = &p_if->in_data; + + /* Initialize the structures */ + p_own_pcr->start = p_own_pcr->end = 0; /* empty FIFO */ + vlc_mutex_init( &p_own_pcr->lock ); + p_in_data->start = p_in_data->end = 0; /* empty FIFO */ + vlc_mutex_init( &p_in_data->lock ); + vlc_cond_init( &p_in_data->notfull ); + vlc_cond_init( &p_in_data->notempty ); + + p_ps->pes_type = NO_PES; + p_ps->pes_id = 0; + p_ps->private_id = 0; + p_ps->pes_size = 0; + p_ps->to_skip = 0; + p_ps->pmt_counter = 0; + p_ps->pat_counter = 0; + for( i=0; i<256; i++ ) + p_ps->association_table[i] = 0; + p_ps->offset = 0; + p_ps->found_pts = 0; + p_ps->found_streams = 0; + p_ps->pcr_pid = p_if->options.pcr_pid; + + p_ps->ps_buffer = malloc(PS_BUFFER_SIZE); + /* those 2 addresses are initialized so that a new packet is read */ + p_ps->ps_data = p_ps->ps_buffer + PS_BUFFER_SIZE - 1; + /* fix the first byte stuff */ + p_ps->ps_data[0] = 0x00; + p_ps->ps_end = p_ps->ps_buffer + PS_BUFFER_SIZE; + + /* Fill the fifo until it is full */ + ps_fill( p_if, 0 ); + /* Launch the thread which fills the fifo */ + vlc_thread_create( &p_if->disk_thread, "disk thread", (vlc_thread_func_t)input_DiskThread, p_if ); + /* Init the synchronization XXX add error detection !!! */ + init_synchro( p_if ); +} + +/****************************************************************************** + * ps_read : ps reading method + ******************************************************************************/ + +ssize_t ps_read (int fd, ps_t * p_ps, void *ts) +{ + int pid, readbytes = 0; + int datasize; + p_ps->ts_written = 0; + + while(p_ps->ts_to_write) + { + + /* if there's not enough data to send */ + if((datasize = p_ps->ps_end - p_ps->ps_data) <= TS_PACKET_SIZE) + { + /* copy the remaining bits at the beginning of the PS buffer */ + memmove ( p_ps->ps_buffer, p_ps->ps_data, datasize); + /* read some bytes */ + readbytes = safe_read(fd, p_ps->ps_buffer + datasize, PS_BUFFER_SIZE - datasize); + + if(readbytes == 0) + { + fprintf (stderr,"ps READ ERROR\n"); + return -1; + } + p_ps->ps_data = p_ps->ps_buffer; + p_ps->ps_end = p_ps->ps_data + datasize + readbytes; + } + + //printf("offset is %x, pes total size is %x, to skip is %x\n", p_ps->offset, p_ps->pes_size, p_ps->to_skip ); + if( p_ps->to_skip == 0 && p_ps->offset == p_ps->pes_size ) + { + if( p_ps->ps_data[0] || p_ps->ps_data[1] || (p_ps->ps_data[2] != 0x01) ) + { + fprintf (stderr,"Error: not a startcode (0x%.2x%.2x%.2x instead of 0x000001)\n", p_ps->ps_data[0], p_ps->ps_data[1], p_ps->ps_data[2] ); + return -1; + } + + p_ps->pes_type = NO_PES; + p_ps->offset = 0; + p_ps->pes_size = (p_ps->ps_data[4] << 8) + p_ps->ps_data[5] + 6; + p_ps->has_pts = p_ps->ps_data[7] & 0xc0; + } + + /* if the actual data we have in pes_data is not a PES, then + * we read the next one. */ + if( (p_ps->pes_type == NO_PES) && !p_ps->to_skip ) + { + p_ps->pes_id = p_ps->ps_data[3]; + + if (p_ps->pes_id == 0xbd) + { + p_ps->private_id = p_ps->ps_data[ 9 + p_ps->ps_data[8] ]; + if ((p_ps->private_id & 0xf0) == 0x80) + { + /* flux audio ac3 */ + p_ps->pes_type = AC3_PES; + } + else if ((p_ps->private_id & 0xf0) == 0x20) + { + /* subtitles */ + p_ps->pes_type = SUBTITLE_PES; + } + else + { + /* unknown private data */ + p_ps->pes_type = PRIVATE_PES; + } + } + else if ((p_ps->pes_id & 0xe0) == 0xc0) + { + /* flux audio */ + p_ps->pes_type = AUDIO_PES; + //write (1, p_ps->ps_data + 9 + p_ps->ps_data[8], 2048 - (9 + p_ps->ps_data[8])); + } + else if ((p_ps->pes_id & 0xf0) == 0xe0) + { + /* flux video */ + p_ps->pes_type = VIDEO_PES; + } + else if (p_ps->pes_id == 0xba) + { + p_ps->pes_type = NO_PES; + p_ps->pes_size = 14; /* 8 extra characters after 0x000001ba**** */ + p_ps->to_skip = 14; + } + else + { + p_ps->pes_type = UNKNOWN_PES; + p_ps->to_skip = p_ps->pes_size; + } + } + + if( p_ps->to_skip ) + { + if( p_ps->to_skip < TS_PACKET_SIZE ) + { + p_ps->ps_data += p_ps->to_skip; + p_ps->offset += p_ps->to_skip; + p_ps->to_skip = 0; + } + else + { + p_ps->ps_data += TS_PACKET_SIZE; + p_ps->offset += TS_PACKET_SIZE; + p_ps->to_skip -= TS_PACKET_SIZE; + } + } + + /* now that we know what we have, we can either + * write this packet's data in the buffer, skip it, + * or write a PMT or PAT table and wait for the next + * turn before writing the packet. */ + switch (p_ps->sent_ts & 0xff) + { + case 0x80: + write_pmt(p_ps,ts); + p_ps->pmt_counter++; + p_ps->ts_to_write--; p_ps->ts_written++; ts+=188; + break; + case 0x00: + write_pat(p_ps,ts); + p_ps->pat_counter++; + p_ps->ts_to_write--; p_ps->ts_written++; ts+=188; + break; + } + + /* if there's still no found PCR_PID, and no PTS in this PES, we trash it */ + if (!p_ps->found_pts) + { + if (p_ps->has_pts) + { + fprintf(stderr, "found a PTS, at last ...\n"); + p_ps->found_pts = 1; + } + else + p_ps->pes_type = NO_PES; + } + + if (p_ps->ts_to_write) + { + switch(p_ps->pes_type) + { + case VIDEO_PES: + case AUDIO_PES: + case SUBTITLE_PES: + case AC3_PES: + pid = get_pid (p_ps); + write_media_ts(p_ps, ts, pid); + p_ps->ts_to_write--; p_ps->ts_written++; ts+=188; + p_ps->media_counter[pid]++; + break; + case UNKNOWN_PES: + default: + p_ps->pes_type = NO_PES; + break; + } + } + } + + //p_ps->ps_data += TS_PACKET_SIZE; + + return p_ps->ts_written; +} + +/****************************************************************************** + * ps_fill : Fill the data buffer with TS created from a PS file + ******************************************************************************/ + +void ps_fill( input_file_t * p_if, boolean_t wait ) +{ + in_data_t * p_in_data = &p_if->in_data; + ps_t * p_ps = &p_if->ps; + int fd = p_if->options.in; + int i, how_many; + int pcr_flag; + file_ts_packet *ts; + + /* How many TS packet for the next UDP packet */ + how_many = TS_IN_UDP; + + pcr_flag = 0; + /* for every single TS packet */ + while( !p_if->b_die ) + { + /* wait until we have one free item to store the UDP packet read */ + vlc_mutex_lock(&p_in_data->lock); + while((p_in_data->end+BUF_SIZE+1-p_in_data->start)%(BUF_SIZE+1) == BUF_SIZE ) + { + /* The buffer is full */ + if(wait) + { + vlc_cond_wait(&p_in_data->notfull, &p_in_data->lock); + if( p_if->b_die ) + return; + } + else + { + vlc_mutex_unlock(&p_in_data->lock); + if (!pcr_flag) + { + intf_ErrMsg( "input error: bad PCR PID\n" ); + } + return; + } + } + vlc_mutex_unlock(&p_in_data->lock); + + /* read a whole UDP packet from the file */ + p_ps->ts_to_write = how_many; + if(ps_read(fd, p_ps, ts = (file_ts_packet *)(p_in_data->buf + p_in_data->end)) != how_many) + { + msleep( 50000 ); /* XXX we need an INPUT_IDLE */ + intf_ErrMsg( "input error: read() error\n" ); + } + + /* Scan to mark TS packets containing a PCR */ + for(i=0; ipcr_pid, ts); + } + + vlc_mutex_lock(&p_in_data->lock); + p_in_data->end++; + p_in_data->end %= BUF_SIZE+1; + vlc_cond_signal(&p_in_data->notempty); + vlc_mutex_unlock(&p_in_data->lock); + } +} + +int init_synchro( input_file_t * p_if ) +{ + int i, pcr_count; + int howmany = TS_IN_UDP; + file_ts_packet * ts; + synchro_t * p_synchro = &p_if->synchro; + in_data_t * p_in_data = &p_if->in_data; + own_pcr_t * p_own_pcr = &p_if->own_pcr; + + p_synchro->slope = 0; + pcr_count = 0; + + /* + * Initialisation of the synchro mecanism : wait for 1 PCR + * to evaluate delta_clock + */ + + while( 1 ) + { + vlc_mutex_lock( &p_in_data->lock ); + + while( p_in_data->end == p_in_data->start ) + { + vlc_cond_wait(&p_in_data->notempty, &p_in_data->lock); + } + /* + if( p_in_data->end == p_in_data->start ) + { + intf_ErrMsg( "input error: init_synchro error, not enough PCR found\n" ); + return( -1 ); + } + */ + vlc_mutex_unlock( &p_in_data->lock ); + + ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start); + for( i=0 ; i < howmany ; i++, ts++ ) + { + if( ts == p_own_pcr->buf[p_own_pcr->start] && !(((u8*)ts)[5] & 0x80) ) + { + p_synchro->last_pcr = ts; + p_synchro->last_pcr_time = ConvertPCRTime( ts ); + p_synchro->delta_clock = mdate() - ConvertPCRTime(ts); + adjust( p_if, ts ); + pcr_count++; + } + } + + vlc_mutex_lock( &p_in_data->lock ); + p_in_data->start++; + p_in_data->start %= BUF_SIZE + 1; + vlc_cond_signal( &p_in_data->notfull ); + vlc_mutex_unlock( &p_in_data->lock ); + + if(pcr_count) + break; + } + return( 0 ); +} + +/***************************************************************************** + * input_FileOpen : open a file descriptor + *****************************************************************************/ + +void input_DiskThread( input_file_t * p_if ) +{ + ps_fill( p_if, 1 ); + vlc_thread_exit(); +} + /***************************************************************************** * input_FileOpen : open a file descriptor *****************************************************************************/ int input_FileOpen( input_thread_t *p_input ) { - /* XXX?? */ - return( 1 ); + options_t * p_options = &input_file.options; + + p_options->in = open( p_input->psz_source, O_RDONLY ); + if( p_options->in < 0 ) + { + intf_ErrMsg( "input error: cannot open the file %s", p_input->psz_source ); + } + + input_file.b_die = 0; + read( p_options->in, &p_options->i_file_type, 1 ); + + switch( p_options->i_file_type ) + { + case 0x00: + p_options->pcr_pid = PCR_PID; + ps_thread( &input_file ); + break; + case 0x47: + intf_ErrMsg( "input error: ts file are not currently supported\n" ); + return( 1 ); + default: + intf_ErrMsg( "input error: cannot determine stream type\n" ); + return( 1 ); + } + + + return( 0 ); } /***************************************************************************** @@ -52,8 +968,52 @@ int input_FileOpen( input_thread_t *p_input ) int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector, size_t i_count ) { - /* XXX?? */ - return( -1 ); + in_data_t * p_in_data = &input_file.in_data; + synchro_t * p_synchro = &input_file.synchro; + own_pcr_t * p_own_pcr = &input_file.own_pcr; + int i, howmany; + file_ts_packet * ts; + + /* XXX XXX XXX + * End condition not verified, should put a flag in ps_fill + */ + howmany = TS_IN_UDP; + //fprintf( stderr, "XXX icount = %d\n", (int)i_count ); + + vlc_mutex_lock( &p_in_data->lock ); + while( p_in_data->end == p_in_data->start ) + { + if( !input_file.b_die ) + vlc_cond_wait( &p_in_data->notempty, &p_in_data->lock ); + } + vlc_mutex_unlock( &p_in_data->lock ); + + ts = (file_ts_packet*)(p_in_data->buf + p_in_data->start); + for( i=0 ; i < howmany ; i++, ts++ ) + { + if( p_synchro->slope && (i == howmany-1) ) + { + wait_a_moment( &input_file, ts ); + } + if( ts == p_own_pcr->buf[p_own_pcr->start] ) + { + /* the TS packet contains a PCR, so we try to adjust the clock */ + adjust( &input_file, ts ); + } + } + + for( i=0 ; ilock); + p_in_data->start++; + p_in_data->start %= BUF_SIZE + 1; + vlc_cond_signal(&p_in_data->notfull); + vlc_mutex_unlock(&p_in_data->lock); + + return( 188*howmany ); } /***************************************************************************** @@ -61,5 +1021,9 @@ int input_FileRead( input_thread_t *p_input, const struct iovec *p_vector, *****************************************************************************/ void input_FileClose( input_thread_t *p_input ) { - /* XXX?? */ + input_file.b_die = 1; + vlc_cond_signal( &input_file.in_data.notfull ); + vlc_thread_join( input_file.disk_thread ); + + close( input_file.options.in ); } diff --git a/src/interface/intf_msg.c b/src/interface/intf_msg.c index d00b7d175b..80ba35313b 100644 --- a/src/interface/intf_msg.c +++ b/src/interface/intf_msg.c @@ -349,7 +349,7 @@ static void QueueMsg( intf_msg_t *p_msg, int i_type, char *psz_format, va_list a * Convert message to string */ #ifdef SYS_BEOS - psz_str = (char*) malloc( INTF_MAX_MSG_SIZE ); + psz_str = (char*) malloc( strlen(psz_format) + INTF_MAX_MSG_SIZE ); vsprintf( psz_str, psz_format, ap ); #else vasprintf( &psz_str, psz_format, ap ); diff --git a/src/interface/main.c b/src/interface/main.c index c50474fe37..3b8ab51f00 100644 --- a/src/interface/main.c +++ b/src/interface/main.c @@ -48,6 +48,10 @@ #include "audio_output.h" +#ifdef SYS_BEOS +#include "beos_specific.h" +#endif + #include "main.h" /***************************************************************************** @@ -146,6 +150,13 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) main_t main_data; /* root of all data - see main.h */ p_main = &main_data; /* set up the global variable */ + /* + * System specific initialization code + */ +#ifdef SYS_BEOS + beos_Init(); +#endif + /* * Read configuration, initialize messages interface and set up program */ @@ -221,6 +232,13 @@ int main( int i_argc, char *ppsz_argv[], char *ppsz_env[] ) input_VlanDestroy(); } + /* + * System specific cleaning code + */ +#ifdef SYS_BEOS + beos_Clean(); +#endif + /* * Terminate messages interface and program */ diff --git a/src/misc/beos_specific.cpp b/src/misc/beos_specific.cpp new file mode 100644 index 0000000000..276391f579 --- /dev/null +++ b/src/misc/beos_specific.cpp @@ -0,0 +1,94 @@ +/***************************************************************************** + * beos_init.cpp: Initialization for BeOS specific features + ***************************************************************************** + * Copyright (C) 1999, 2000 VideoLAN + * + * 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 + * 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-1307, USA. + *****************************************************************************/ +#include "defs.h" + +#include +#include +#include +#include +#include + +extern "C" +{ +#include "common.h" +#include "threads.h" +#include "mtime.h" +} +#include "beos_specific.h" + + + +/***************************************************************************** + * Static vars + *****************************************************************************/ +static vlc_thread_t beos_app_thread; +static char * psz_beos_program_path; + + +extern "C" +{ + +void beos_AppThread( void * args ) +{ + BApplication * BeApp = new BApplication("application/x-VLC"); + BeApp->Run(); + delete BeApp; +} + +void beos_Init( void ) +{ + int i_lenght; + BPath path; + app_info info; + + vlc_thread_create( &beos_app_thread, "app thread", (vlc_thread_func_t)beos_AppThread, 0 ); + msleep( 100000 ); + // FIXME: we need to verify that be_app is initialized and the msleep is not enough + // but the following code does not work as it should and I have no good + // solution at the moment. + //while( be_app == NULL ) + // msleep( 5000 ); + + be_app->GetAppInfo(&info); + BEntry entry(&info.ref); + entry.GetPath(&path); + path.GetParent(&path); + i_lenght = strlen( path.Path() ); + psz_beos_program_path = (char*) malloc( i_lenght+1 ); /* XXX */ + strcpy( psz_beos_program_path, path.Path() ); +} + +void beos_Clean( void ) +{ + free( psz_beos_program_path ); /* XXX */ + be_app->PostMessage( B_QUIT_REQUESTED ); + vlc_thread_join( beos_app_thread ); +} + +char * beos_GetProgramPath( void ) +{ + return( psz_beos_program_path ); +} + +} /* extern "C" */ \ No newline at end of file diff --git a/src/misc/plugins.c b/src/misc/plugins.c index 7a4d9fba7b..40e16b18eb 100644 --- a/src/misc/plugins.c +++ b/src/misc/plugins.c @@ -35,6 +35,10 @@ #error no dynamic plugins available on your system ! #endif +#ifdef SYS_BEOS +#include "beos_specific.h" +#endif + #include "plugins.h" #define PLUGIN_PATH_COUNT 5 @@ -54,15 +58,21 @@ int RequestPlugin ( plugin_id_t * p_plugin, char * psz_mask, char * psz_name ) for ( i_count = 0 ; i_count < PLUGIN_PATH_COUNT ; i_count++ ) { +#ifdef SYS_BEOS + char * psz_program_path; + + psz_program_path = beos_GetProgramPath(); + psz_plugin = malloc( strlen(psz_plugin_path[i_count]) + strlen(psz_program_path) + i_length + 6 ); + sprintf( psz_plugin, "%s/%s/%s_%s.so", psz_program_path, psz_plugin_path[i_count], psz_mask, psz_name ); +#else psz_plugin = malloc( strlen(psz_plugin_path[i_count]) + i_length + 6 ); sprintf( psz_plugin, "%s/%s_%s.so", psz_plugin_path[i_count], psz_mask, psz_name ); +#endif #if defined(HAVE_DLFCN_H) *p_plugin = dlopen( psz_plugin, RTLD_NOW | RTLD_GLOBAL ); - #elif defined(HAVE_IMAGE_H) *p_plugin = load_add_on( psz_plugin ); - #endif free( psz_plugin ); @@ -70,11 +80,9 @@ int RequestPlugin ( plugin_id_t * p_plugin, char * psz_mask, char * psz_name ) #if defined(HAVE_DLFCN_H) if( *p_plugin != NULL ) return( 0 ); - #elif defined(HAVE_IMAGE_H) if( *p_plugin >= 0 ) return( 0 ); - #endif } @@ -85,10 +93,8 @@ void TrashPlugin ( plugin_id_t plugin ) { #if defined(HAVE_DLFCN_H) dlclose( plugin ); - #elif defined(HAVE_IMAGE_H) unload_add_on( plugin ); - #endif } @@ -96,15 +102,12 @@ void * GetPluginFunction ( plugin_id_t plugin, char *psz_name ) { #if defined(HAVE_DLFCN_H) return( dlsym(plugin, psz_name) ); - #elif defined(HAVE_IMAGE_H) - void * p_func; - + void * p_func; if( get_image_symbol( plugin, psz_name, B_SYMBOL_TYPE_TEXT, &p_func ) ) return( NULL ); else return( p_func ); - #endif } diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 6a6aab89c5..e8dd110669 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -1191,7 +1191,9 @@ last_display_date = display_date; if( b_display && !(p_vout->i_changes & VOUT_NODISPLAY_CHANGE) ) { p_vout->p_sys_display( p_vout ); +#ifndef SYS_BEOS p_vout->i_buffer_index = ++p_vout->i_buffer_index & 1; +#endif } /* diff --git a/src/video_parser/vpar_blocks.c b/src/video_parser/vpar_blocks.c index 0794c6aee5..9c478f942c 100644 --- a/src/video_parser/vpar_blocks.c +++ b/src/video_parser/vpar_blocks.c @@ -439,7 +439,7 @@ void vpar_InitCrop( vpar_thread_t * p_vpar ) *****************************************************************************/ /* Function for filling up the lookup table for mb_addr_inc */ -static void __inline__ FillMbAddrIncTable( vpar_thread_t * p_vpar, +static void FillMbAddrIncTable( vpar_thread_t * p_vpar, int i_start, int i_end, int i_step, int * pi_value, int i_length ) { @@ -502,7 +502,7 @@ void vpar_InitMbAddrInc( vpar_thread_t * p_vpar ) *****************************************************************************/ /* Fonction for filling up the tables */ -static void __inline__ FillMBType( vpar_thread_t * p_vpar, +static void FillMBType( vpar_thread_t * p_vpar, int i_mb_type, int i_start, int i_end, @@ -563,7 +563,7 @@ void vpar_InitBMBType( vpar_thread_t * p_vpar ) *****************************************************************************/ /* First fonction for filling the table */ -static void __inline__ FillDCTTable( dct_lookup_t * p_tab_dest, dct_lookup_t * p_tab_src, +static void FillDCTTable( dct_lookup_t * p_tab_dest, dct_lookup_t * p_tab_src, int i_step, int i_nb_elem, int i_offset ) { int i_dummy, i_dummy2; @@ -619,7 +619,7 @@ void vpar_InitDCTTables( vpar_thread_t * p_vpar ) /***************************************************************************** * DecodeMPEG1NonIntra : decode MPEG-1 non-intra blocks *****************************************************************************/ -static __inline__ void DecodeMPEG1NonIntra( vpar_thread_t * p_vpar, +static void DecodeMPEG1NonIntra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b, int i_chroma_format ) { @@ -730,7 +730,7 @@ static __inline__ void DecodeMPEG1NonIntra( vpar_thread_t * p_vpar, /***************************************************************************** * DecodeMPEG1Intra : decode MPEG-1 intra blocks *****************************************************************************/ -static __inline__ void DecodeMPEG1Intra( vpar_thread_t * p_vpar, +static void DecodeMPEG1Intra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b , int i_chroma_format ) { @@ -877,7 +877,7 @@ static __inline__ void DecodeMPEG1Intra( vpar_thread_t * p_vpar, /***************************************************************************** * DecodeMPEG2NonIntra : decode MPEG-2 non-intra blocks *****************************************************************************/ -static __inline__ void DecodeMPEG2NonIntra( vpar_thread_t * p_vpar, +static void DecodeMPEG2NonIntra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b, int i_chroma_format ) { @@ -986,7 +986,7 @@ static __inline__ void DecodeMPEG2NonIntra( vpar_thread_t * p_vpar, /***************************************************************************** * DecodeMPEG2Intra : decode MPEG-2 intra blocks *****************************************************************************/ -static __inline__ void DecodeMPEG2Intra( vpar_thread_t * p_vpar, +static void DecodeMPEG2Intra( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_b, int i_chroma_format ) { @@ -1136,7 +1136,7 @@ static __inline__ void DecodeMPEG2Intra( vpar_thread_t * p_vpar, /**************************************************************************** * MotionCode : Parse the next motion code ****************************************************************************/ -static __inline__ int MotionCode( vpar_thread_t * p_vpar ) +static int MotionCode( vpar_thread_t * p_vpar ) { int i_code; static lookup_t pl_mv_tab0[8] = @@ -1185,7 +1185,7 @@ static __inline__ int MotionCode( vpar_thread_t * p_vpar ) /**************************************************************************** * DecodeMotionVector : Decode a motion_vector ****************************************************************************/ -static __inline__ void DecodeMotionVector( int * pi_prediction, int i_r_size, +static void DecodeMotionVector( int * pi_prediction, int i_r_size, int i_motion_code, int i_motion_residual, int i_full_pel ) { int i_limit, i_vector; @@ -1212,7 +1212,7 @@ static __inline__ void DecodeMotionVector( int * pi_prediction, int i_r_size, /**************************************************************************** * MotionVector : Parse the next motion_vector field ****************************************************************************/ -static __inline__ void MotionVector( vpar_thread_t * p_vpar, +static void MotionVector( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_r, int i_s, int i_full_pel, int i_structure ) { @@ -1321,7 +1321,7 @@ static __inline__ void MotionVector( vpar_thread_t * p_vpar, /***************************************************************************** * DecodeMVMPEG1 : Parse the next MPEG-1 motion vectors *****************************************************************************/ -static __inline__ void DecodeMVMPEG1( vpar_thread_t * p_vpar, +static void DecodeMVMPEG1( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_s, int i_structure ) { MotionVector( p_vpar, p_mb, 0, i_s, @@ -1331,7 +1331,7 @@ static __inline__ void DecodeMVMPEG1( vpar_thread_t * p_vpar, /***************************************************************************** * DecodeMVMPEG2 : Parse the next MPEG-2 motion_vectors field *****************************************************************************/ -static __inline__ void DecodeMVMPEG2( vpar_thread_t * p_vpar, +static void DecodeMVMPEG2( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_s, int i_structure ) { if( p_vpar->mb.i_mv_count == 1 ) @@ -1364,7 +1364,7 @@ static __inline__ void DecodeMVMPEG2( vpar_thread_t * p_vpar, /***************************************************************************** * MacroblockAddressIncrement : Get the macroblock_address_increment field *****************************************************************************/ -static __inline__ int MacroblockAddressIncrement( vpar_thread_t * p_vpar ) +static int MacroblockAddressIncrement( vpar_thread_t * p_vpar ) { int i_addr_inc = 0; /* Index in the lookup table mb_addr_inc */ @@ -1390,7 +1390,7 @@ static __inline__ int MacroblockAddressIncrement( vpar_thread_t * p_vpar ) /***************************************************************************** * IMBType : macroblock_type in I pictures *****************************************************************************/ -static __inline__ int IMBType( vpar_thread_t * p_vpar ) +static int IMBType( vpar_thread_t * p_vpar ) { /* Take two bits for testing */ int i_type = ShowBits( &p_vpar->bit_stream, 2 ); @@ -1408,7 +1408,7 @@ static __inline__ int IMBType( vpar_thread_t * p_vpar ) /***************************************************************************** * PMBType : macroblock_type in P pictures *****************************************************************************/ -static __inline__ int PMBType( vpar_thread_t * p_vpar ) +static int PMBType( vpar_thread_t * p_vpar ) { /* Testing on 6 bits */ int i_type = ShowBits( &p_vpar->bit_stream, 6 ); @@ -1422,7 +1422,7 @@ static __inline__ int PMBType( vpar_thread_t * p_vpar ) /***************************************************************************** * BMBType : macroblock_type in B pictures *****************************************************************************/ -static __inline__ int BMBType( vpar_thread_t * p_vpar ) +static int BMBType( vpar_thread_t * p_vpar ) { /* Testing on 6 bits */ int i_type = ShowBits( &p_vpar->bit_stream, 6 ); @@ -1437,7 +1437,7 @@ static __inline__ int BMBType( vpar_thread_t * p_vpar ) /***************************************************************************** * DMBType : macroblock_type in D pictures *****************************************************************************/ -static __inline__ int DMBType( vpar_thread_t * p_vpar ) +static int DMBType( vpar_thread_t * p_vpar ) { return GetBits( &p_vpar->bit_stream, 1 ); } @@ -1445,7 +1445,7 @@ static __inline__ int DMBType( vpar_thread_t * p_vpar ) /***************************************************************************** * CodedPattern420 : coded_block_pattern with 4:2:0 chroma *****************************************************************************/ -static __inline__ int CodedPattern420( vpar_thread_t * p_vpar ) +static int CodedPattern420( vpar_thread_t * p_vpar ) { /* Take the max 9 bits length vlc code for testing */ int i_vlc = ShowBits( &p_vpar->bit_stream, 9 ); @@ -1460,7 +1460,7 @@ static __inline__ int CodedPattern420( vpar_thread_t * p_vpar ) /***************************************************************************** * CodedPattern422 : coded_block_pattern with 4:2:2 chroma *****************************************************************************/ -static __inline__ int CodedPattern422( vpar_thread_t * p_vpar ) +static int CodedPattern422( vpar_thread_t * p_vpar ) { int i_vlc = ShowBits( &p_vpar->bit_stream, 9 ); @@ -1474,7 +1474,7 @@ static __inline__ int CodedPattern422( vpar_thread_t * p_vpar ) /***************************************************************************** * CodedPattern444 : coded_block_pattern with 4:4:4 chroma *****************************************************************************/ -static __inline__ int CodedPattern444( vpar_thread_t * p_vpar ) +static int CodedPattern444( vpar_thread_t * p_vpar ) { int i_vlc = ShowBits( &p_vpar->bit_stream, 9 ); @@ -1487,7 +1487,7 @@ static __inline__ int CodedPattern444( vpar_thread_t * p_vpar ) /***************************************************************************** * InitMacroblock : Initialize macroblock values *****************************************************************************/ -static __inline__ void InitMacroblock( vpar_thread_t * p_vpar, +static void InitMacroblock( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_coding_type, int i_chroma_format, int i_structure, @@ -1522,7 +1522,7 @@ static __inline__ void InitMacroblock( vpar_thread_t * p_vpar, /***************************************************************************** * UpdateContext : Update the p_vpar contextual values *****************************************************************************/ -static __inline__ void UpdateContext( vpar_thread_t * p_vpar, int i_structure ) +static void UpdateContext( vpar_thread_t * p_vpar, int i_structure ) { /* Update macroblock real position. */ p_vpar->mb.i_l_x += 16; @@ -1540,7 +1540,7 @@ static __inline__ void UpdateContext( vpar_thread_t * p_vpar, int i_structure ) /***************************************************************************** * SkippedMacroblock : Generate a skipped macroblock with NULL motion vector *****************************************************************************/ -static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb, +static void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb, int i_mb_base, int i_coding_type, int i_chroma_format, int i_structure, @@ -1600,7 +1600,7 @@ static __inline__ void SkippedMacroblock( vpar_thread_t * p_vpar, int i_mb, /***************************************************************************** * MacroblockModes : Get the macroblock_modes structure *****************************************************************************/ -static __inline__ void MacroblockModes( vpar_thread_t * p_vpar, +static void MacroblockModes( vpar_thread_t * p_vpar, macroblock_t * p_mb, int i_chroma_format, int i_coding_type, @@ -1747,7 +1747,7 @@ if( p_vpar->picture.b_error ) \ } \ } -static __inline__ void ParseMacroblock( +static void ParseMacroblock( vpar_thread_t * p_vpar, int * pi_mb_address, /* previous address to be * used for mb_addr_incr */ @@ -1981,7 +1981,7 @@ i_count++; /***************************************************************************** * SliceHeader : Parse the next slice structure *****************************************************************************/ -static __inline__ void SliceHeader( vpar_thread_t * p_vpar, +static void SliceHeader( vpar_thread_t * p_vpar, int * pi_mb_address, int i_mb_base, u32 i_vert_code, boolean_t b_high, boolean_t b_dp_scalable, @@ -2057,7 +2057,7 @@ static __inline__ void SliceHeader( vpar_thread_t * p_vpar, /***************************************************************************** * PictureData : Parse off all macroblocks (ISO/IEC 13818-2 6.2.3.7) *****************************************************************************/ -static __inline__ void PictureData( vpar_thread_t * p_vpar, int i_mb_base, +static void PictureData( vpar_thread_t * p_vpar, int i_mb_base, boolean_t b_high, boolean_t b_dp_scalable, boolean_t b_mpeg2, int i_coding_type, int i_chroma_format, int i_structure,