view aviwrite.c @ 300:df3f7a25584c

audio format support, realloc() cleanup
author arpi_esp
date Sat, 07 Apr 2001 00:51:38 +0000
parents 3b5f5d1c5041
children 8511095c5283
line wrap: on
line source


void write_avi_chunk(FILE *f,unsigned int id,int len,void* data){

fwrite(&id,4,1,f);
fwrite(&len,4,1,f);
if(len>0){
  if(data){
    // DATA
    fwrite(data,len,1,f);
    if(len&1){  // padding
      unsigned char zerobyte=0;
      fwrite(&zerobyte,1,1,f);
    }
  } else {
    // JUNK
    char *avi_junk_data="[= MPlayer junk data! =]";
    if(len&1) ++len; // padding
    while(len>0){
      int l=strlen(avi_junk_data);
      if(l>len) l=len;
      fwrite(avi_junk_data,l,1,f);
      len-=l;
    }
  }
}

}


void write_avi_list(FILE *f,unsigned int id,int len){
  unsigned int list_id=FOURCC_LIST;
  len+=4; // list fix
  fwrite(&list_id,4,1,f);
  fwrite(&len,4,1,f);
  fwrite(&id,4,1,f);
}

struct {
  MainAVIHeader avih;
  AVIStreamHeader video;
  BITMAPINFOHEADER bih;
  unsigned int movi_start;
  unsigned int movi_end;
  unsigned int file_end;
} wah;

void write_avi_header(FILE *f){
  unsigned int riff[3];
  // RIFF header:
  riff[0]=mmioFOURCC('R','I','F','F');
  riff[1]=wah.file_end;  // filesize
  riff[2]=formtypeAVI; // 'AVI '
  fwrite(&riff,12,1,f);
  // AVI header:
  write_avi_list(f,listtypeAVIHEADER,sizeof(wah.avih)+8+12+sizeof(wah.video)+8+sizeof(wah.bih)+8);
  write_avi_chunk(f,ckidAVIMAINHDR,sizeof(wah.avih),&wah.avih);
  // stream header:
  write_avi_list(f,listtypeSTREAMHEADER,sizeof(wah.video)+8+sizeof(wah.bih)+8);
  write_avi_chunk(f,ckidSTREAMHEADER,sizeof(wah.video),&wah.video);
  write_avi_chunk(f,ckidSTREAMFORMAT,sizeof(wah.bih),&wah.bih);
  // JUNK:  
  write_avi_chunk(f,ckidAVIPADDING,2048-(ftell(f)&2047)-8,NULL);
  // 'movi' header:
  write_avi_list(f,listtypeAVIMOVIE,wah.movi_end-ftell(f)-12);
  wah.movi_start=ftell(f);
}

// called _before_ encoding:  (write placeholders and video info)
void write_avi_header_1(FILE *f,int fcc,float fps,int width,int height){
  int frames=8*3600*fps; // 8 hours
  
  wah.file_end=
  wah.movi_end=0x7f000000;

  wah.avih.dwMicroSecPerFrame=1000000.0f/fps;
  wah.avih.dwMaxBytesPerSec=fps*500000; // ?????
  wah.avih.dwPaddingGranularity=1; // padding
  wah.avih.dwFlags=AVIF_ISINTERLEAVED;
  wah.avih.dwTotalFrames=frames;
  wah.avih.dwInitialFrames=0;
  wah.avih.dwStreams=1;
  wah.avih.dwSuggestedBufferSize=0x10000; // 1MB
  wah.avih.dwWidth=width;
  wah.avih.dwHeight=height;
  wah.avih.dwReserved[0]=
  wah.avih.dwReserved[1]=
  wah.avih.dwReserved[2]=
  wah.avih.dwReserved[3]=0;
  
  wah.video.fccType=streamtypeVIDEO;
  wah.video.fccHandler=fcc;
  wah.video.dwFlags=0;
  wah.video.wPriority=0;
  wah.video.wLanguage=0;
  wah.video.dwInitialFrames=0;
  wah.video.dwScale=10000;
  wah.video.dwRate=fps*10000;
  wah.video.dwStart=0;
  wah.video.dwLength=frames;
  wah.video.dwSuggestedBufferSize=0x100000; // 1MB ????
  wah.video.dwQuality=10000;
  wah.video.dwSampleSize=width*height*3;
  
  wah.bih.biSize=sizeof(wah.bih); // 40 ?
  wah.bih.biWidth=width;
  wah.bih.biHeight=height;
  wah.bih.biPlanes=1;
  wah.bih.biBitCount=24;
  wah.bih.biCompression=fcc;
  wah.bih.biSizeImage=3*width*height;
  wah.bih.biXPelsPerMeter=
  wah.bih.biYPelsPerMeter=
  wah.bih.biClrUsed=
  wah.bih.biClrImportant=0;

  write_avi_header(f);  
}

void avi_fixate(){
  // append index and fix avi headers:
  FILE *f1=fopen(encode_name,"r+");
  FILE *f2;

  if(!f1) return; // error
  
  fseek(f1,0,SEEK_END);
  wah.file_end=wah.movi_end=ftell(f1);

  // index:
  if(encode_index_name && (f2=fopen(encode_index_name,"rb"))){
    AVIINDEXENTRY idx;
    unsigned int pos=0;
    int frames=0;
    write_avi_chunk(f1,ckidAVINEWINDEX,0,NULL);
    while(fread(&idx,sizeof(idx),1,f2)>0){
      idx.dwChunkOffset-=wah.movi_start-4;
      fwrite(&idx,sizeof(idx),1,f1);
      ++frames;
    }
    fclose(f2);
    unlink(encode_index_name);
    wah.file_end=ftell(f1);
    // re-write idx1 length:
    pos=wah.file_end-wah.movi_end-8;
    fseek(f1,wah.movi_end+4,SEEK_SET);
    fwrite(&pos,4,1,f1);
    // fixup frames:
    wah.avih.dwTotalFrames=frames;
    wah.video.dwLength=frames;
  }

  // re-write avi header:
  fseek(f1,0,SEEK_SET);
  write_avi_header(f1);

  fclose(f1);
  
}