summaryrefslogtreecommitdiffstats
path: root/mplayer.c
diff options
context:
space:
mode:
Diffstat (limited to 'mplayer.c')
-rw-r--r--mplayer.c1957
1 files changed, 1957 insertions, 0 deletions
diff --git a/mplayer.c b/mplayer.c
new file mode 100644
index 0000000000..e174b03093
--- /dev/null
+++ b/mplayer.c
@@ -0,0 +1,1957 @@
+// AVI & MPEG Player v0.11 (C) 2000-2001. by A'rpi/ESP-team
+
+//#define SIMULATE_ALSA
+
+#ifdef USE_XMMP_AUDIO
+#define OUTBURST 4096
+#else
+//#define OUTBURST 1024
+#define OUTBURST 512
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <signal.h>
+
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/soundcard.h>
+#include <linux/cdrom.h>
+
+#include "version.h"
+#include "config.h"
+
+// CODECS:
+#include "mp3lib/mp3.h"
+#include "libac3/ac3.h"
+#include "libmpeg2/mpeg2.h"
+#include "libmpeg2/mpeg2_internal.h"
+
+#include "loader.h"
+#include "wine/avifmt.h"
+//#include "libvo/video_out.h" // included from mpeg2.h
+
+#include "opendivx/decore.h"
+
+
+#ifdef USE_XMMP_AUDIO
+#include "libxmm/xmmp.h"
+#include "libxmm/libxmm.h"
+XMM xmm;
+XMM_PluginSound *pSound=NULL;
+#endif
+
+
+extern char* win32_codec_name; // must be set before calling DrvOpen() !!!
+
+extern int errno;
+
+#include "linux/getch2.h"
+#include "linux/keycodes.h"
+#include "linux/timer.h"
+#include "linux/shmem.h"
+
+#ifdef HAVE_LIRC
+#include "lirc_mp.h"
+#endif
+
+#include "help_mp.h"
+
+#define DEBUG if(0)
+static int verbose=0;
+
+static int max_framesize=0;
+
+static int dbg_es_sent=0;
+static int dbg_es_rcvd=0;
+
+//static int show_packets=0;
+
+//**************************************************************************//
+
+typedef struct {
+ // file:
+ MainAVIHeader avih;
+ unsigned int movi_start;
+ unsigned int movi_end;
+ // index:
+ AVIINDEXENTRY* idx;
+ int idx_size;
+ int idx_pos;
+ int idx_pos_a;
+ int idx_pos_v;
+ int idx_offset; // ennyit kell hozzaadni az index offset ertekekhez
+// int a_idx;
+// int v_idx;
+ // video:
+ AVIStreamHeader video;
+ char *video_codec;
+ BITMAPINFOHEADER bih; // in format
+ BITMAPINFOHEADER o_bih; // out format
+ HIC hic;
+ void *our_out_buffer;
+ unsigned int bitrate;
+ // video format flags: (filled by codecs.c)
+ char yuv_supported; // 1 if codec support YUY2 output format
+ char yuv_hack_needed; // requires for divx & mpeg4
+ char no_32bpp_support; // requires for INDEO 3.x, 4.x
+ char flipped; // image is upside-down
+ // audio:
+ AVIStreamHeader audio;
+ char *audio_codec;
+ int audio_seekable;
+ char wf_ext[64]; // in format
+ WAVEFORMATEX wf; // out format
+ HACMSTREAM srcstream;
+ int audio_in_minsize;
+ int audio_out_minsize;
+} avi_header_t;
+
+avi_header_t avi_header;
+
+#include "aviprint.c"
+#include "codecs.c"
+
+extern picture_t *picture;
+
+char* encode_name=NULL;
+char* encode_index_name=NULL;
+int encode_bitrate=0;
+
+//**************************************************************************//
+
+#include "stream.c"
+#include "demuxer.c"
+#include "demux_avi.c"
+#include "demux_mpg.c"
+
+demuxer_t *demuxer=NULL;
+demux_stream_t *d_audio=NULL;
+demux_stream_t *d_video=NULL;
+
+// MPEG video stream parser:
+#include "parse_es.c"
+
+//int mp3_read(char *buf,int size){
+int mplayer_audio_read(char *buf,int size){
+ int len;
+ len=demux_read_data(d_audio,buf,size);
+ return len;
+}
+
+static void ac3_fill_buffer(uint8_t **start,uint8_t **end){
+ int len=ds_get_packet(d_audio,(char**)start);
+ //printf("<ac3:%d>\n",len);
+ if(len<0)
+ *start = *end = NULL;
+ else
+ *end = *start + len;
+}
+
+#include "alaw.c"
+
+#include "xa/xa_gsm.h"
+
+unsigned char *opendivx_src[3];
+int opendivx_stride[3];
+
+void my_convert_yuv(unsigned char *puc_y, int stride_y,
+ unsigned char *puc_u, unsigned char *puc_v, int stride_uv,
+ unsigned char *bmp, int width_y, int height_y){
+
+// vo_functions_t *video_out=(vo_functions_t *) bmp;
+
+// printf("convert_yuv called %dx%d stride: %d,%d\n",width_y,height_y,stride_y,stride_uv);
+
+ opendivx_src[0]=puc_y;
+ opendivx_src[1]=puc_u;
+ opendivx_src[2]=puc_v;
+
+ opendivx_stride[0]=stride_y;
+ opendivx_stride[1]=stride_uv;
+ opendivx_stride[2]=stride_uv;
+}
+
+//**************************************************************************//
+
+#ifdef SIMULATE_ALSA
+// Simulate ALSA buffering on OSS device :) (for testing...)
+
+#define fake_ALSA_size 32768
+char fake_ALSA_buffer[fake_ALSA_size];
+int fake_ALSA_len=0;
+
+void fake_ALSA_write(int audio_fd,char* a_buffer,int len){
+while(len>0){
+ int x=fake_ALSA_size-fake_ALSA_len;
+ if(x>0){
+ if(x>len) x=len;
+ memcpy(&fake_ALSA_buffer[fake_ALSA_len],a_buffer,x);
+ fake_ALSA_len+=x;len-=x;
+ }
+ if(fake_ALSA_len>=fake_ALSA_size){
+ write(audio_fd,fake_ALSA_buffer,fake_ALSA_len);
+ fake_ALSA_len=0;
+ }
+}
+}
+#endif
+//**************************************************************************//
+
+// AVI file header reader/parser/writer:
+#include "aviheader.c"
+#include "aviwrite.c"
+
+// ASF headers:
+#include "asfheader.c"
+#include "demux_asf.c"
+
+// DLL codecs init routines
+#include "dll_init.c"
+
+// MPEG video codec process controller:
+#include "codecctrl.c"
+
+//**************************************************************************//
+
+static vo_functions_t *video_out=NULL;
+
+static int play_in_bg=0;
+
+void exit_player(char* how){
+ if(how) printf("\nExiting... (%s)\n",how);
+ printf("max framesize was %d bytes\n",max_framesize);
+ // restore terminal:
+ getch2_disable();
+ if(child_pid){
+ // MPEG
+ // printf("\n\n");
+ //send_cmd(data_fifo,0);usleep(50000); // EOF request
+ DEBUG_SIG { printf("Sending TERM signal to CTRL...\n");DEBUG_SIGNALS_SLEEP}
+ kill(child_pid,SIGTERM);
+ usleep(10000); // kill & wait 10ms
+ DEBUG_SIG { printf("Closing PIPEs...\n");DEBUG_SIGNALS_SLEEP}
+ close(control_fifo);
+ close(data_fifo);
+ DEBUG_SIG { printf("Freeing shmem...\n");DEBUG_SIGNALS_SLEEP}
+ if(videobuffer) shmem_free(videobuffer);
+ DEBUG_SIG { printf("Exiting...\n");DEBUG_SIGNALS_SLEEP}
+ } else {
+ // AVI
+ video_out->uninit();
+ }
+#ifdef USE_XMMP_AUDIO
+ if(verbose) printf("XMM: closing audio driver...\n");
+ if(pSound){
+ pSound->Exit( pSound );
+ xmm_Exit( &xmm );
+ }
+#endif
+ if(encode_name) avi_fixate();
+#ifdef HAVE_LIRC
+ lirc_mp_cleanup();
+#endif
+ //if(play_in_bg) system("xsetroot -solid \\#000000");
+ exit(1);
+}
+
+static char* current_module=NULL; // for debugging
+
+void exit_sighandler(int x){
+ static int sig_count=0;
+ ++sig_count;
+ if(sig_count==2) exit(1);
+ if(sig_count>2){
+ // can't stop :(
+ kill(getpid(),SIGKILL);
+ }
+ printf("\nMPlayer interrupted by signal %d in module: %s \n",x,
+ current_module?current_module:"unknown"
+ );
+ exit_player(NULL);
+}
+
+int divx_quality=0;
+
+int main(int argc,char* argv[]){
+char* filename=NULL; //"MI2-Trailer.avi";
+int i;
+int seek_to_sec=0;
+int seek_to_byte=0;
+int f; // filedes
+int stream_type;
+stream_t* stream=NULL;
+int file_format=DEMUXER_TYPE_UNKNOWN;
+int has_audio=1; // audio format 0=none 1=mpeg 2=pcm 3=ac3 4=win32 5=alaw 6=msgsm
+int has_video=0; // video format 0=none 1=mpeg 2=win32 3=OpenDivX
+//
+int audio_format=0; // override
+#ifdef ALSA_TIMER
+int alsa=1;
+#else
+int alsa=0;
+#endif
+int audio_buffer_size=-1;
+int audio_id=-1;
+int video_id=-1;
+float default_max_pts_correction=0.01f;
+int delay_corrected=1;
+float force_fps=0;
+float default_fps=25;
+float audio_delay=0;
+int vcd_track=0;
+#ifdef VCD_CACHE
+int vcd_cache_size=128;
+#endif
+int no_index=0;
+#ifdef AVI_SYNC_BPS
+int pts_from_bps=1;
+#else
+int pts_from_bps=0;
+#endif
+char* title="MPlayer";
+// screen info:
+char* video_driver=NULL; //"mga"; // default
+int fullscreen=0;
+int screen_size_x=SCREEN_SIZE_X;
+int screen_size_y=SCREEN_SIZE_Y;
+int screen_size_xy=0;
+// movie info:
+int movie_size_x=0;
+int movie_size_y=0;
+int out_fmt=0;
+char *dsp="/dev/dsp";
+int force_ni=0;
+
+ printf("%s",banner_text);
+
+for(i=1;i<argc;i++){
+ if(strcmp(argv[i],"-o")==0){
+ printf("Option -o has been changed to -vo (video-out), use -vo !\n");
+ exit(1);
+ } else
+ if(strcmp(argv[i],"-vo")==0) video_driver=argv[++i]; else
+ if(strcmp(argv[i],"-dsp")==0) dsp=argv[++i]; else
+ if(strcmp(argv[i],"-encode")==0) encode_name=argv[++i]; else
+ if(strcmp(argv[i],"-bg")==0) play_in_bg=1; else
+ if(strcmp(argv[i],"-sb")==0) seek_to_byte=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-ss")==0) seek_to_sec=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-nosound")==0) has_audio=0; else
+ if(strcmp(argv[i],"-abs")==0) audio_buffer_size=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-delay")==0) audio_delay=strtod(argv[++i],NULL); else
+#ifdef AVI_SYNC_BPS
+ if(strcmp(argv[i],"-nobps")==0) pts_from_bps=0; else
+#else
+ if(strcmp(argv[i],"-bps")==0) pts_from_bps=1; else
+#endif
+#ifdef ALSA_TIMER
+ if(strcmp(argv[i],"-noalsa")==0) alsa=0; else
+#else
+ if(strcmp(argv[i],"-alsa")==0) alsa=1; else
+#endif
+ if(strcmp(argv[i],"-ni")==0) force_ni=1; else
+ if(strcmp(argv[i],"-aid")==0) audio_id=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-vid")==0) video_id=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-auds")==0) avi_header.audio_codec=argv[++i]; else
+ if(strcmp(argv[i],"-vids")==0) avi_header.video_codec=argv[++i]; else
+ if(strcmp(argv[i],"-mc")==0) default_max_pts_correction=strtod(argv[++i],NULL); else
+ if(strcmp(argv[i],"-fps")==0) force_fps=strtod(argv[++i],NULL); else
+ if(strcmp(argv[i],"-afm")==0) audio_format=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-vcd")==0) vcd_track=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-divxq")==0) divx_quality=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-br")==0) encode_bitrate=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-x")==0) screen_size_x=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-y")==0) screen_size_y=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-xy")==0) screen_size_xy=strtol(argv[++i],NULL,0); else
+ if(strcmp(argv[i],"-fs")==0) fullscreen=1; else
+ if(strcmp(argv[i],"-noidx")==0) no_index=1; else
+ if(strcmp(argv[i],"-v")==0) ++verbose; else
+ if(strcmp(argv[i],"-h")==0) break; else
+ if(strcmp(argv[i],"--help")==0) break; else
+ { if(filename){ printf("invalid option: %s\n",filename);exit(1);}
+ filename=argv[i];
+ }
+}
+
+// Many users forget to include command line in bugreports...
+if(verbose){
+ printf("CommandLine:");
+ for(i=1;i<argc;i++)printf(" '%s'",argv[i]);
+ printf("\n");
+}
+
+if(video_driver && strcmp(video_driver,"help")==0){
+ printf("Available video output drivers:\n");
+ i=0;
+ while (video_out_drivers[i]) {
+ const vo_info_t *info = video_out_drivers[i++]->get_info ();
+ printf("\t%s\t%s\n", info->short_name, info->name);
+ }
+ printf("\n");
+ exit(0);
+}
+
+// check video_out driver name:
+ if(!video_driver)
+ video_out=video_out_drivers[0];
+ else
+ for (i=0; video_out_drivers[i] != NULL; i++){
+ const vo_info_t *info = video_out_drivers[i]->get_info ();
+ if(strcmp(info->short_name,video_driver) == 0){
+ video_out = video_out_drivers[i];break;
+ }
+ }
+ if(!video_out){
+ printf("Invalid video output driver name: %s\n",video_driver);
+ return 0;
+ }
+
+
+if(!filename){
+ if(vcd_track) filename="/dev/cdrom";
+ else
+ //filename="MI2-Trailer.avi";
+ { printf("%s",help_text); exit(0);}
+}
+
+
+if(vcd_track){
+//============ Open VideoCD track ==============
+ f=open(filename,O_RDONLY);
+ if(f<0){ printf("CD-ROM Device '%s' not found!\n",filename);return 1; }
+ vcd_read_toc(f);
+ if(!vcd_seek_to_track(f,vcd_track)){ printf("Error selecting VCD track!\n");return 1;}
+ seek_to_byte+=VCD_SECTOR_DATA*vcd_get_msf();
+ if(verbose) printf("VCD start byte position: 0x%X\n",seek_to_byte);
+ stream_type=STREAMTYPE_VCD;
+#ifdef VCD_CACHE
+ vcd_cache_init(vcd_cache_size);
+#endif
+} else {
+//============ Open plain FILE ============
+ f=open(filename,O_RDONLY);
+ if(f<0){ printf("File not found: '%s'\n",filename);return 1; }
+ stream_type=STREAMTYPE_FILE;
+}
+
+stream=new_stream(f,stream_type);
+
+//============ Open & Sync stream and detect file format ===============
+
+if(has_audio==0) audio_id=-2; // do NOT read audio packets...
+
+//=============== Try to open as AVI file: =================
+stream_reset(stream);
+demuxer=new_demuxer(stream,DEMUXER_TYPE_AVI,audio_id,video_id);
+stream_seek(demuxer->stream,seek_to_byte);
+{ //---- RIFF header:
+ int id=stream_read_dword_le(demuxer->stream); // "RIFF"
+ if(id==mmioFOURCC('R','I','F','F')){
+ stream_read_dword_le(demuxer->stream); //filesize
+ id=stream_read_dword_le(demuxer->stream); // "AVI "
+ if(id==formtypeAVI){
+ printf("Detected AVI file format!\n");
+ file_format=DEMUXER_TYPE_AVI;
+ }
+ }
+}
+//=============== Try to open as ASF file: =================
+if(file_format==DEMUXER_TYPE_UNKNOWN){
+ stream_reset(stream);
+ demuxer=new_demuxer(stream,DEMUXER_TYPE_ASF,audio_id,video_id);
+ stream_seek(demuxer->stream,seek_to_byte);
+ if(asf_check_header()){
+ printf("Detected ASF file format!\n");
+ file_format=DEMUXER_TYPE_ASF;
+// printf("!!! ASF files not (yet) supported !!!\n");exit(1);
+ }
+}
+//=============== Try to open as MPEG-PS file: =================
+if(file_format==DEMUXER_TYPE_UNKNOWN){
+ stream_reset(stream);
+ demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_PS,audio_id,video_id);
+ stream_seek(demuxer->stream,seek_to_byte);
+ if(audio_format) demuxer->audio->type=audio_format; // override audio format
+ if(ds_fill_buffer(demuxer->video)){
+ printf("Detected MPEG-PS file format!\n");
+ file_format=DEMUXER_TYPE_MPEG_PS;
+ } else {
+ // some hack to get meaningfull error messages to our unhappy users:
+// if(num_elementary_packets100>16 &&
+// abs(num_elementary_packets101-num_elementary_packets100)<8){
+ if(num_elementary_packets100>=2 && num_elementary_packets101>=2 &&
+ abs(num_elementary_packets101-num_elementary_packets100)<8){
+ file_format=DEMUXER_TYPE_MPEG_ES; // <-- hack is here :)
+ } else {
+ if(demuxer->synced==2)
+ printf("Missing MPEG video stream!? contact the author, it may be a bug :(\n");
+ else
+ printf("Not MPEG System Stream format... (maybe Transport Stream?)\n");
+ }
+ }
+}
+//=============== Try to open as MPEG-ES file: =================
+if(file_format==DEMUXER_TYPE_MPEG_ES){ // little hack, see above!
+ stream_reset(stream);
+ demuxer=new_demuxer(stream,DEMUXER_TYPE_MPEG_ES,audio_id,video_id);
+ stream_seek(demuxer->stream,seek_to_byte);
+ if(!ds_fill_buffer(demuxer->video)){
+ printf("Invalid MPEG-ES stream??? contact the author, it may be a bug :(\n");
+ file_format=DEMUXER_TYPE_UNKNOWN;
+ } else {
+ printf("Detected MPEG-ES file format!\n");
+ }
+}
+//=============== Unknown, exiting... ===========================
+if(file_format==DEMUXER_TYPE_UNKNOWN){
+ printf("============= Sorry, this file format not recognized/supported ===============\n");
+ printf("=== If this file is an AVI, ASF or MPEG stream, please contact the author! ===\n");
+ exit(1);
+}
+//====== File format recognized, set up these for compatibility: =========
+d_audio=demuxer->audio;
+d_video=demuxer->video;
+
+switch(file_format){
+ case DEMUXER_TYPE_AVI: {
+ //---- AVI header:
+ read_avi_header(no_index);
+ stream_reset(demuxer->stream);
+ stream_seek(demuxer->stream,avi_header.movi_start);
+ avi_header.idx_pos=0;
+ avi_header.idx_pos_a=0;
+ avi_header.idx_pos_v=0;
+ if(avi_header.idx_size>0){
+ // decide index format:
+ if(avi_header.idx[0].dwChunkOffset<avi_header.movi_start)
+ avi_header.idx_offset=avi_header.movi_start-4;
+ else
+ avi_header.idx_offset=0;
+ if(verbose) printf("AVI index offset: %d\n",avi_header.idx_offset);
+ }
+ demuxer->endpos=avi_header.movi_end;
+
+ if(avi_header.idx_size>0){
+ // check that file is non-interleaved:
+ int i;
+ int a_pos=-1;
+ int v_pos=-1;
+ for(i=0;i<avi_header.idx_size;i++){
+ AVIINDEXENTRY* idx=&avi_header.idx[i];
+ demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
+ int pos=idx->dwChunkOffset+avi_header.idx_offset;
+ if(a_pos==-1 && ds==demuxer->audio){
+ a_pos=pos;
+ if(v_pos!=-1) break;
+ }
+ if(v_pos==-1 && ds==demuxer->video){
+ v_pos=pos;
+ if(a_pos!=-1) break;
+ }
+ }
+ if(v_pos==-1){
+ printf("AVI_NI: missing video stream!? contact the author, it may be a bug :(\n");
+ exit(1);
+ }
+ if(a_pos==-1){
+ printf("AVI_NI: No audio stream found -> nosound\n");
+ has_audio=0;
+ } else {
+ if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB
+ printf("Detected NON-INTERLEAVED AVI file-format!\n");
+ file_format=DEMUXER_TYPE_AVI_NI; // HACK!!!!
+ demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!
+ pts_from_bps=1; // force BPS sync!
+ }
+ }
+ } else {
+ // no index
+ if(force_ni){
+ printf("Using NON-INTERLEAVED Broken AVI file-format!\n");
+// file_format=DEMUXER_TYPE_AVI_NI; // HACK!!!!
+ demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!
+ avi_header.idx_pos_a=
+ avi_header.idx_pos_v=avi_header.movi_start;
+ pts_from_bps=1; // force BPS sync!
+ }
+ }
+
+ if(!ds_fill_buffer(d_video)){
+ printf("AVI: missing video stream!? contact the author, it may be a bug :(\n");
+ exit(1);
+ }
+ has_video=2;
+ // Decide audio format:
+ if(audio_format)
+ has_audio=audio_format; // override type
+ else if(has_audio)
+ switch(((WAVEFORMATEX *)&avi_header.wf_ext)->wFormatTag){
+ case 0:
+ has_audio=0;break; // disable/no audio
+ case 6:
+ avi_header.audio_seekable=1;
+ has_audio=5;break; // aLaw
+ case 0x31:
+ case 0x32:
+ has_audio=6;break; // MS-GSM
+ case 0x50:
+#ifdef DEFAULT_MPG123
+ case 0x55:
+#endif
+ avi_header.audio_seekable=1;
+ has_audio=1;break; // MPEG
+ case 0x01:
+ avi_header.audio_seekable=1;
+ has_audio=2;break; // PCM
+ case 0x2000:
+ avi_header.audio_seekable=1;
+ has_audio=3;break; // AC3
+ default:
+ avi_header.audio_seekable=0;
+ has_audio=4; // Win32/ACM
+ }
+ if(verbose) printf("detected AVI audio format: %d\n",has_audio);
+ if(has_audio==4){
+ if(!avi_header.audio_codec) avi_header.audio_codec=get_auds_codec_name();
+ if(!avi_header.audio_codec) has_audio=0; // unknown win32 codec
+ if(verbose) printf("win32 audio codec: '%s'\n",avi_header.audio_codec);
+ }
+ if(has_audio){
+ if(verbose) printf("AVI: Searching for audio stream (id:%d)\n",d_audio->id);
+ if(!ds_fill_buffer(d_audio)){
+ printf("AVI: No Audio stream found... ->nosound\n");
+ has_audio=0;
+ }
+ }
+ default_fps=(float)avi_header.video.dwRate/(float)avi_header.video.dwScale;
+ break;
+ }
+ case DEMUXER_TYPE_ASF: {
+ //---- ASF header:
+ read_asf_header();
+ stream_reset(demuxer->stream);
+ stream_seek(demuxer->stream,avi_header.movi_start);
+ avi_header.idx_pos=0;
+#if 0
+ if(avi_header.idx_size>0){
+ // decide index format:
+ if(avi_header.idx[0].dwChunkOffset<avi_header.movi_start)
+ avi_header.idx_offset=avi_header.movi_start-4;
+ else
+ avi_header.idx_offset=0;
+ if(verbose) printf("ASF index offset: %d\n",avi_header.idx_offset);
+ }
+#endif
+ demuxer->endpos=avi_header.movi_end;
+ if(!ds_fill_buffer(d_video)){
+ printf("ASF: missing video stream!? contact the author, it may be a bug :(\n");
+ exit(1);
+ }
+ has_video=2;
+ // Decide audio format:
+ if(audio_format)
+ has_audio=audio_format; // override type
+ else if(has_audio)
+ switch(((WAVEFORMATEX *)&avi_header.wf_ext)->wFormatTag){
+ case 0:
+ has_audio=0;break; // disable/no audio
+ case 6:
+ avi_header.audio_seekable=1;
+ has_audio=5;break; // aLaw
+ case 0x31:
+ case 0x32:
+ has_audio=6;break; // MS-GSM
+ case 0x50:
+#ifdef DEFAULT_MPG123
+ case 0x55:
+#endif
+ avi_header.audio_seekable=1;
+ has_audio=1;break; // MPEG
+ case 0x01:
+ avi_header.audio_seekable=1;
+ has_audio=2;break; // PCM
+ case 0x2000:
+ avi_header.audio_seekable=1;
+ has_audio=3;break; // AC3
+ default:
+ avi_header.audio_seekable=0;
+ has_audio=4; // Win32/ACM
+ }
+ if(verbose) printf("detected ASF audio format: %d\n",has_audio);
+ if(has_audio==4){
+ if(!avi_header.audio_codec) avi_header.audio_codec=get_auds_codec_name();
+ if(!avi_header.audio_codec) has_audio=0; // unknown win32 codec
+ if(verbose) printf("win32 audio codec: '%s'\n",avi_header.audio_codec);
+ }
+ if(has_audio){
+ if(verbose) printf("ASF: Searching for audio stream (id:%d)\n",d_audio->id);
+ if(!ds_fill_buffer(d_audio)){
+ printf("ASF: No Audio stream found... ->nosound\n");
+ has_audio=0;
+ }
+ }
+ break;
+ }
+ case DEMUXER_TYPE_MPEG_ES: {
+ demuxer->audio->type=0;
+ has_audio=0; // ES streams has no audio channel
+ has_video=1; // mpeg video
+ break;
+ }
+ case DEMUXER_TYPE_MPEG_PS: {
+ if(has_audio)
+ if(!ds_fill_buffer(d_audio)){
+ printf("MPEG: No Audio stream found... ->nosound\n");
+ has_audio=0;
+ } else {
+ has_audio=d_audio->type;
+ }
+ if(verbose) printf("detected MPG-PS audio format: %d\n",has_audio);
+ has_video=1; // mpeg video
+ break;
+ }
+} // switch(file_format)
+
+if(verbose) printf("file successfully opened (has_audio=%d)\n",has_audio);
+
+fflush(stdout);
+
+//================== Init VIDEO (codec & libvo) ==========================
+
+if(has_video==2){
+ if(avi_header.video.fccHandler==mmioFOURCC('d', 'v', 'x', '1')) has_video=3;
+ if(avi_header.video.fccHandler==mmioFOURCC('d', 'i', 'v', 'x')) has_video=3;
+ if(avi_header.bih.biCompression==mmioFOURCC('d', 'v', 'x', '1')) has_video=3;
+ if(avi_header.bih.biCompression==mmioFOURCC('d', 'i', 'v', 'x')) has_video=3;
+}
+
+switch(has_video){
+ case 2: {
+ if(!avi_header.video_codec) avi_header.video_codec=get_vids_codec_name();
+ if(verbose)
+ printf("win32 video codec: '%s' %s%s%s\n",avi_header.video_codec,
+ avi_header.yuv_supported?"[YUV]":"",
+ avi_header.yuv_hack_needed?"[hack]":"",
+ avi_header.flipped?"[FLIP]":""
+ );
+ if(!avi_header.video_codec) exit(1); // unknown video codec
+ if(avi_header.yuv_supported && video_out->query_format(IMGFMT_YUY2)) out_fmt=IMGFMT_YUY2; else
+ if(avi_header.no_32bpp_support && video_out->query_format(IMGFMT_BGR|32)) out_fmt=IMGFMT_BGR|24; else
+ if(video_out->query_format(IMGFMT_BGR|15)) out_fmt=IMGFMT_BGR|16; else
+ if(video_out->query_format(IMGFMT_BGR|16)) out_fmt=IMGFMT_BGR|16; else
+ if(video_out->query_format(IMGFMT_BGR|24)) out_fmt=IMGFMT_BGR|24; else
+ if(video_out->query_format(IMGFMT_BGR|32)) out_fmt=IMGFMT_BGR|32; else {
+ printf("Sorry, selected video_out device is incompatible with this codec.\n");
+ printf("(It can't show 24bpp or 32bpp RGB images. Try to run X at 24/32bpp!)\n");
+// printf("(cannot convert between YUY2, YV12 and RGB colorspace formats)\n");
+ exit(1);
+ }
+ //if(verbose) printf("AVI out_fmt=%X\n",out_fmt);
+ if(verbose) if(out_fmt==IMGFMT_YUY2) printf("Using YUV/YUY2 video output format!\n");
+ if(!init_video_codec(out_fmt)) exit(1);
+ if(verbose) printf("INFO: Win32 video codec init OK!\n");
+ if(out_fmt==(IMGFMT_BGR|16)) out_fmt=IMGFMT_BGR|15; // fix bpp
+
+ // calculating video bitrate:
+ avi_header.bitrate=avi_header.movi_end-avi_header.movi_start-avi_header.idx_size*8;
+ if(avi_header.audio.fccType) avi_header.bitrate-=avi_header.audio.dwLength;
+ if(verbose) printf("AVI video length=%d\n",avi_header.bitrate);
+ avi_header.bitrate=((float)avi_header.bitrate/(float)avi_header.video.dwLength)
+ *((float)avi_header.video.dwRate/(float)avi_header.video.dwScale);
+// default_fps=(float)avi_header.video.dwRate/(float)avi_header.video.dwScale;
+ printf("VIDEO: [%.4s] %dx%d %dbpp %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
+ &avi_header.bih.biCompression,
+ avi_header.bih.biWidth,
+ avi_header.bih.biHeight,
+ avi_header.bih.biBitCount,
+ default_fps,
+ avi_header.bitrate*0.008f,
+ avi_header.bitrate/1024.0f );
+
+ // display info:
+ movie_size_x=avi_header.o_bih.biWidth;
+ movie_size_y=abs(avi_header.o_bih.biHeight);
+ break;
+ }
+ case 3: { // OpenDivX
+ if(verbose) printf("OpenDivX video codec\n");
+ out_fmt=IMGFMT_YV12;
+ { DEC_PARAM dec_param;
+ DEC_SET dec_set;
+ dec_param.x_dim = avi_header.bih.biWidth;
+ dec_param.y_dim = avi_header.bih.biHeight;
+ dec_param.color_depth = 32;
+ decore(0x123, DEC_OPT_INIT, &dec_param, NULL);
+ dec_set.postproc_level = divx_quality;
+ decore(0x123, DEC_OPT_SETPP, &dec_set, NULL);
+ }
+ if(verbose) printf("INFO: OpenDivX video codec init OK!\n");
+
+ // calculating video bitrate:
+ avi_header.bitrate=avi_header.movi_end-avi_header.movi_start-avi_header.idx_size*8;
+ if(avi_header.audio.fccType) avi_header.bitrate-=avi_header.audio.dwLength;
+ if(verbose) printf("AVI video length=%d\n",avi_header.bitrate);
+ avi_header.bitrate=((float)avi_header.bitrate/(float)avi_header.video.dwLength)
+ *((float)avi_header.video.dwRate/(float)avi_header.video.dwScale);
+// default_fps=(float)avi_header.video.dwRate/(float)avi_header.video.dwScale;
+ printf("VIDEO: [%.4s] %dx%d %dbpp %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
+ &avi_header.bih.biCompression,
+ avi_header.bih.biWidth,
+ avi_header.bih.biHeight,
+ avi_header.bih.biBitCount,
+ default_fps,
+ avi_header.bitrate*0.008f,
+ avi_header.bitrate/1024.0f );
+
+ // display info:
+// movie_size_x=avi_header.bih.biWidth+(divx_quality?0:64);
+ movie_size_x=avi_header.bih.biWidth;
+ movie_size_y=abs(avi_header.bih.biHeight);
+ break;
+ }
+ case 1: {
+ // Find sequence_header first:
+ if(verbose) printf("Searching for sequence header... ");fflush(stdout);
+ while(1){
+ int i=sync_video_packet(d_video);
+ if(i==0x1B3) break; // found it!
+ if(!i || !skip_video_packet(d_video)){
+ if(verbose) printf("NONE :(\n");
+ printf("MPEG: FATAL: EOF while searching for sequence header\n");
+ exit(1);
+ }
+ }
+ if(verbose) printf("FOUND!\n");
+ // allocate some shared memory for the video packet buffer:
+ videobuffer=shmem_alloc(VIDEOBUFFER_SIZE);
+ if(!videobuffer){ printf("Cannot allocate shared memory\n");exit(0);}
+ // init libmpeg2:
+ mpeg2_init();
+ picture->pp_options=divx_quality;
+ if(verbose) printf("mpeg2_init() ok\n");
+ // ========= Read & process sequence header & extension ============
+ videobuf_len=0;
+ if(!read_video_packet(d_video)){ printf("FATAL: Cannot read sequence header!\n");return 1;}
+ if(header_process_sequence_header (picture, &videobuffer[4])) {
+ printf ("bad sequence header!\n"); return 1;
+ }
+ if(sync_video_packet(d_video)==0x1B5){ // next packet is seq. ext.
+ videobuf_len=0;
+ if(!read_video_packet(d_video)){ printf("FATAL: Cannot read sequence header extension!\n");return 1;}
+ if(header_process_extension (picture, &videobuffer[4])) {
+ printf ("bad sequence header extension!\n"); return 1;
+ }
+ }
+ default_fps=picture->frame_rate*0.0001f;
+ if(verbose) printf("mpeg bitrate: %d (%X)\n",picture->bitrate,picture->bitrate);
+ printf("VIDEO: %s %dx%d (aspect %d) %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
+ picture->mpeg1?"MPEG1":"MPEG2",
+ picture->display_picture_width,picture->display_picture_height,
+ picture->aspect_ratio_information,
+ default_fps,
+ picture->bitrate*0.5f,
+ picture->bitrate/16.0f );
+ // display info:
+ out_fmt=IMGFMT_YV12;
+// movie_size_x=picture->coded_picture_width;
+ movie_size_x=picture->display_picture_width;
+ movie_size_y=picture->display_picture_height;
+ break;
+ }
+}
+
+// ================== Init output files for encoding ===============
+ if(encode_name){
+ // encode file!!!
+ FILE *encode_file=fopen(encode_name,"rb");
+ if(encode_file){
+ fclose(encode_file);
+ printf("File already exists: %s (don't overwrite your favourite AVI!)\n",encode_name);
+ return 0;
+ }
+ encode_file=fopen(encode_name,"wb");
+ if(!encode_file){
+ printf("Cannot create file for encoding\n");
+ return 0;
+ }
+ write_avi_header_1(encode_file,mmioFOURCC('d', 'i', 'v', 'x'),default_fps,movie_size_x,movie_size_y);
+ fclose(encode_file);
+ encode_index_name=malloc(strlen(encode_name)+8);
+ strcpy(encode_index_name,encode_name);
+ strcat(encode_index_name,".index");
+ if((encode_file=fopen(encode_index_name,"wb")))
+ fclose(encode_file);
+ else encode_index_name=NULL;
+ has_audio=0; // disable audio !!!!!
+ }
+
+// ========== Init keyboard FIFO (connection to libvo) ============
+
+make_pipe(&keyb_fifo_get,&keyb_fifo_put);
+
+// ========== Init display (movie_size_x*movie_size_y/out_fmt) ============
+
+#ifdef X11_FULLSCREEN
+ if(fullscreen){
+ if(vo_init()){
+ //if(verbose) printf("X11 running at %dx%d depth: %d\n",vo_screenwidth,vo_screenheight,vo_depthonscreen);
+ }
+ if(!screen_size_xy) screen_size_xy=vo_screenwidth; // scale with asp.ratio
+ }
+#endif
+
+ if(screen_size_xy>0){
+ if(screen_size_xy<=8){
+ screen_size_x=screen_size_xy*movie_size_x;
+ screen_size_y=screen_size_xy*movie_size_y;
+ } else {
+ screen_size_x=screen_size_xy;
+ screen_size_y=screen_size_xy*movie_size_y/movie_size_x;
+ }
+ } else {
+ if(screen_size_x<=8) screen_size_x*=movie_size_x;
+ if(screen_size_y<=8) screen_size_y*=movie_size_y;
+ }
+ if(verbose) printf("Destination size: %d x %d out_fmt=%0X\n",
+ screen_size_x,screen_size_y,out_fmt);
+
+ if(verbose) printf("video_out->init(%dx%d->%dx%d,fs=%d,'%s',0x%X)\n",
+ movie_size_x,movie_size_y,
+ screen_size_x,screen_size_y,
+ fullscreen,title,out_fmt);
+
+ if(video_out->init(movie_size_x,movie_size_y,
+ screen_size_x,screen_size_y,
+ fullscreen,title,out_fmt)){
+ printf("FATAL: Cannot initialize video driver!\n");exit(1);
+ }
+ if(verbose) printf("INFO: Video OUT driver init OK!\n");
+
+ fflush(stdout);
+
+
+if(has_video==1){
+ //================== init mpeg codec ===================
+ mpeg2_allocate_image_buffers (picture);
+ if(verbose) printf("INFO: mpeg2_init_video() OK!\n");
+ // ====== Init MPEG codec process ============
+ make_pipe(&control_fifo,&control_fifo2);
+ make_pipe(&data_fifo2,&data_fifo);
+ // ====== Let's FORK() !!! ===================
+ if((child_pid=fork())==0)
+ mpeg_codec_controller(video_out); // this one is running in a new process!!!!
+ signal(SIGPIPE,SIG_IGN); // Ignore "Broken pipe" signal (codec restarts)
+}
+
+//================== MAIN: ==========================
+{
+char* a_buffer=NULL;
+int a_buffer_len=0;
+int a_buffer_size=0;
+char* a_in_buffer=NULL;
+int a_in_buffer_len=0;
+int a_in_buffer_size=0;
+int audio_fd=-1;
+int pcm_bswap=0;
+float buffer_delay=0;
+float frame_correction=0; // A-V timestamp kulonbseg atlagolas
+int frame_corr_num=0; //
+float a_frame=0; // Audio
+float v_frame=0; // Video
+float time_frame=0; // Timer
+float a_pts=0;
+float v_pts=0;
+float c_total=0;
+float max_pts_correction=default_max_pts_correction;
+int eof=0;
+int force_redraw=0;
+ac3_frame_t *ac3_frame=NULL;
+float num_frames=0; // number of frames played
+//int real_num_frames=0; // number of frames readed
+double video_time_usage=0;
+double vout_time_usage=0;
+double audio_time_usage=0;
+
+#ifdef HAVE_LIRC
+ lirc_mp_setup();
+#endif
+
+#ifdef USE_TERMCAP
+ load_termcap(NULL); // load key-codes
+#endif
+ getch2_enable();
+
+ //========= Catch terminate signals: ================
+ // terminate requests:
+ signal(SIGTERM,exit_sighandler); // kill
+ signal(SIGHUP,exit_sighandler); // kill -HUP / xterm closed
+ signal(SIGINT,exit_sighandler); // Interrupt from keyboard
+ signal(SIGQUIT,exit_sighandler); // Quit from keyboard
+ // fatal errors:
+ signal(SIGBUS,exit_sighandler); // bus error
+ signal(SIGSEGV,exit_sighandler); // segfault
+ signal(SIGILL,exit_sighandler); // illegal instruction
+ signal(SIGFPE,exit_sighandler); // floating point exc.
+ signal(SIGABRT,exit_sighandler); // abort()
+
+//================ SETUP AUDIO ==========================
+ current_module="setup_audio";
+
+if(has_audio){
+
+ if(verbose) printf("Initializing audio codec...\n");
+
+MP3_bps=2;
+pcm_bswap=0;
+a_buffer_size=16384; // default size, maybe not enough for Win32/ACM
+
+if(has_audio==4){
+ // Win32 ACM audio codec:
+ if(init_audio_codec()){
+ MP3_channels=avi_header.wf.nChannels;
+ MP3_samplerate=avi_header.wf.nSamplesPerSec;
+ a_in_buffer_size=avi_header.audio_in_minsize;
+ a_in_buffer=malloc(a_in_buffer_size);
+ a_in_buffer_len=0;
+ if(a_buffer_size<avi_header.audio_out_minsize+OUTBURST)
+ a_buffer_size=avi_header.audio_out_minsize+OUTBURST;
+ } else {
+ printf("Could not load/initialize Win32/ACM AUDIO codec (missing DLL file?)\n");
+ if((((WAVEFORMATEX *)&avi_header.wf_ext)->wFormatTag)==0x55){
+ printf("Audio format is MP3 -> fallback to internal mp3lib/mpg123\n");
+ has_audio=1; // fallback to mp3lib
+ } else
+ has_audio=0; // nosound
+ }
+}
+
+// allocate audio out buffer:
+a_buffer=malloc(a_buffer_size);
+memset(a_buffer,0,a_buffer_size);
+a_buffer_len=0;
+
+if(has_audio==2){
+ if(file_format==DEMUXER_TYPE_AVI || file_format==DEMUXER_TYPE_AVI_NI){
+ // AVI PCM Audio:
+ WAVEFORMATEX *h=(WAVEFORMATEX*)&avi_header.wf_ext;
+ MP3_channels=h->nChannels;
+ MP3_samplerate=h->nSamplesPerSec;
+ MP3_bps=(h->wBitsPerSample+7)/8;
+ } else {
+ // DVD PCM audio:
+ MP3_channels=2;
+ MP3_samplerate=48000;
+ pcm_bswap=1;
+ }
+} else
+if(has_audio==3){
+ // Dolby AC3 audio:
+ ac3_config.fill_buffer_callback = ac3_fill_buffer;
+ ac3_config.num_output_ch = 2;
+ ac3_config.flags = 0;
+#ifdef HAVE_MMX
+ ac3_config.flags |= AC3_MMX_ENABLE;
+#endif
+#ifdef HAVE_3DNOW
+ ac3_config.flags |= AC3_3DNOW_ENABLE;
+#endif
+ ac3_init();
+ ac3_frame = ac3_decode_frame();
+ if(ac3_frame){
+ MP