view aviparse.c @ 1:3b5f5d1c5041

Initial revision
author arpi_esp
date Sat, 24 Feb 2001 20:28:24 +0000
parents
children
line wrap: on
line source

// AVI Parser tool   v0.1   (C) 2000. by A'rpi/ESP-team

#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 <linux/cdrom.h>

#include "config.h"

#include "loader.h"
#include "wine/avifmt.h"
//#include "libvo/video_out.h"

#include "linux/timer.h"
#include "linux/shmem.h"

#include "help_avp.h"

#define DEBUG if(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 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;
  char yuv_supported;   // 1 if codec support YUY2 output format
  char yuv_hack_needed; // requires for divx & mpeg4
  // audio:
  AVIStreamHeader audio;
  char *audio_codec;
  char wf_ext[64];     // in format
  WAVEFORMATEX wf;     // out format
  HACMSTREAM srcstream;
  int audio_minsize;
} avi_header_t;

avi_header_t avi_header;

#include "aviprint.c"
//#include "codecs.c"

//**************************************************************************//
#include "stream.c"
//#include "demuxer.c"
//#include "demux_avi.c"

static stream_t* stream=NULL;

//**************************************************************************//

extern int errno;
static int play_in_bg=0;

void exit_player(){
//  int tmp;
  // restore terminal:
  getch2_disable();
  printf("\n\n");
  if(play_in_bg) system("xsetroot -solid \\#000000");
  exit(1);
}

void exit_sighandler(int x){
  printf("\nmpgplay2 interrupted by signal %d\n",x);
  exit_player();
}


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 has_audio=1;
//int audio_format=0;
//int alsa=0;
//int audio_buffer_size=-1;
int audio_id=-1;
//int video_id=-1;
//float default_max_pts_correction=0.01f;
//int delay_corrected=0;
//float force_fps=0;
//float default_fps=25;
//float audio_delay=0;
int stream_type;
//int elementary_stream=0;
int vcd_track=0;
#ifdef VCD_CACHE
int vcd_cache_size=128;
#endif
//char* video_driver="mga"; // default
//int out_fmt=0;
int idx_filepos=0;
FILE *audiofile=NULL;
FILE *videofile=NULL;
char *audiofile_name=NULL;
char *videofile_name=NULL;

  printf("%s",banner_text);

for(i=1;i<argc;i++){
  if(strcmp(argv[i],"-afile")==0)  audiofile_name=argv[++i]; else
  if(strcmp(argv[i],"-vfile")==0)  videofile_name=argv[++i]; else
//  if(strcmp(argv[i],"-sb")==0) seek_to_byte=strtol(argv[++i],NULL,0); 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],"-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],"-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];
  }
}

if(!filename){
  if(vcd_track) filename="/dev/cdrom"; 
//  else
//  filename="/4/Film/Joan of Arc [Hun DivX]/Joan of Arc - CD2.avi";
  { printf("%s",help_text); exit(0);}
}


if(vcd_track){
//============ Open VideoCD track ==============
  f=open(filename,O_RDONLY);
  if(f<0){ printf("Device not found!\n");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();
  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!\n");return 1; }
  stream_type=STREAMTYPE_FILE;
}

//============ Open & Sync stream and detect file format ===============

stream=new_stream(f,stream_type);
//=============== Read AVI header:
{ //---- RIFF header:
  int id=stream_read_dword_le(stream); // "RIFF"
  if(id!=mmioFOURCC('R','I','F','F')){ printf("Not RIFF format file!\n");return 1; }
  stream_read_dword_le(stream); //filesize
  id=stream_read_dword_le(stream); // "AVI "
  if(id!=formtypeAVI){ printf("Not AVI file!\n");return 1; }
}
//---- AVI header:
avi_header.idx_size=0;
while(1){
  int id=stream_read_dword_le(stream);
  int chunksize,size2;
  static int last_fccType=0;
  //
  if(stream_eof(stream)) break;
  //
  if(id==mmioFOURCC('L','I','S','T')){
    int len=stream_read_dword_le(stream)-4; // list size
    id=stream_read_dword_le(stream);        // list type
    printf("LIST %.4s  len=%d\n",&id,len);
    if(id==listtypeAVIMOVIE){
      // found MOVI header
      avi_header.movi_start=stream_tell(stream);
      avi_header.movi_end=avi_header.movi_start+len;
//      printf("Found movie at 0x%X - 0x%X\n",avi_header.movi_start,avi_header.movi_end);
      len=(len+1)&(~1);
      stream_skip(stream,len);
    }
    continue;
  }
  size2=stream_read_dword_le(stream);
  printf("CHUNK %.4s  len=%d\n",&id,size2);
  chunksize=(size2+1)&(~1);
  switch(id){
    case ckidAVIMAINHDR:          // read 'avih'
      stream_read(stream,(char*) &avi_header.avih,sizeof(avi_header.avih));
      chunksize-=sizeof(avi_header.avih);
      print_avih(&avi_header.avih);
      break;
    case ckidSTREAMHEADER: {      // read 'strh'
      AVIStreamHeader h;
      stream_read(stream,(char*) &h,sizeof(h));
      chunksize-=sizeof(h);
      if(h.fccType==streamtypeVIDEO) memcpy(&avi_header.video,&h,sizeof(h));else
      if(h.fccType==streamtypeAUDIO) memcpy(&avi_header.audio,&h,sizeof(h));
      last_fccType=h.fccType;
      print_strh(&h);
      break; }
    case ckidSTREAMFORMAT: {      // read 'strf'
      if(last_fccType==streamtypeVIDEO){
        stream_read(stream,(char*) &avi_header.bih,sizeof(avi_header.bih));
        chunksize-=sizeof(avi_header.bih);
//        init_video_codec();
//        init_video_out();
      } else
      if(last_fccType==streamtypeAUDIO){
        int z=(chunksize<64)?chunksize:64;
        printf("found 'wf', %d bytes of %d\n",chunksize,sizeof(WAVEFORMATEX));
        stream_read(stream,(char*) &avi_header.wf_ext,z);
        chunksize-=z;
        print_wave_header((WAVEFORMATEX*)&avi_header.wf_ext);
//        init_audio_codec();
//        init_audio_out();
      }
      break;
    }
    case ckidAVINEWINDEX: {
      avi_header.idx_size=size2>>4;
//      printf("Reading INDEX block, %d chunks for %d frames\n",
//        avi_header.idx_size,avi_header.avih.dwTotalFrames);
      avi_header.idx=malloc(avi_header.idx_size<<4);
      idx_filepos=stream_tell(stream);
      stream_read(stream,(char*)avi_header.idx,avi_header.idx_size<<4);
      chunksize-=avi_header.idx_size<<4;
      print_index();
      break;
    }
  }
  if(chunksize>0) stream_skip(stream,chunksize); else
  if(chunksize<0) printf("WARNING!!! chunksize=%d  (id=%.4s)\n",chunksize,&id);
  
}

printf("----------------------------------------------------------------------\n");
printf("Found movie at 0x%X - 0x%X\n",avi_header.movi_start,avi_header.movi_end);
if(avi_header.idx_size<=0){ printf("No index block found!\n");return 0;}
printf("Index block at 0x%X, %d entries for %d frames\n",idx_filepos,
  avi_header.idx_size,avi_header.avih.dwTotalFrames  );

stream_reset(stream);
stream_seek(stream,avi_header.movi_start);
avi_header.idx_pos=0;

if(audiofile_name) audiofile=fopen(audiofile_name,"wb");
if(videofile_name) videofile=fopen(videofile_name,"wb");

for(i=0;i<avi_header.idx_size;i++){
#if 0
    printf("%.4s  %4X  %08X  %d  ",
      &avi_header.idx[i].ckid,
      avi_header.idx[i].dwFlags,
      avi_header.idx[i].dwChunkOffset,
      avi_header.idx[i].dwChunkLength
    );fflush(stdout);
#endif
    if(avi_header.idx[i].ckid&AVIIF_LIST){
//      printf("LIST\n");
    } else {
      int id,size;
      stream_seek(stream,avi_header.movi_start+avi_header.idx[i].dwChunkOffset-4);
      id=stream_read_dword_le(stream);
      size=stream_read_dword_le(stream);
      if(id!=avi_header.idx[i].ckid){
        printf("ChunkID mismatch! raw=%.4s (0x%X) idx=%.4s (0x%X)\n",
          &id,avi_header.movi_start+avi_header.idx[i].dwChunkOffset-4,
          &avi_header.idx[i].ckid,idx_filepos+16*i
        );
        continue;
      }
      if(size!=avi_header.idx[i].dwChunkLength){
        printf("ChunkSize mismatch! raw=%d (0x%X) idx=%d (0x%X)\n",
          size,avi_header.movi_start+avi_header.idx[i].dwChunkOffset-4,
          avi_header.idx[i].dwChunkLength,idx_filepos+16*i
        );
        continue;
      }

      if(id!=mmioFOURCC('J','U','N','K'))
      if(TWOCCFromFOURCC(id)==cktypeWAVEbytes){
          // audio
          int aid=StreamFromFOURCC(id);
          if(audio_id==-1) audio_id=aid;
          if(audio_id==aid){
            if(audiofile){
              void* mem=malloc(size);
              stream_read(stream,mem,size);
              fwrite(mem,size,1,audiofile);
              free(mem);
            }
          } else {
            printf("Invalid audio stream id: %d (%.4s)\n",aid,&id);
          }
      } else 
      if(LOWORD(id)==aviTWOCC('0','0')){
         // video
            if(videofile){
              void* mem=malloc(size);
              stream_read(stream,mem,size);
              fwrite(&size,4,1,videofile);
              fwrite(mem,size,1,videofile);
              free(mem);
            }
      } else {
         // unknown
         printf("Unknown chunk: %.4s (%X)\n",&id,id);
      }

    } // LIST or CHUNK

}

return 0;
}