diff options
Diffstat (limited to 'libmpdemux/aviwrite.c')
-rw-r--r-- | libmpdemux/aviwrite.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/libmpdemux/aviwrite.c b/libmpdemux/aviwrite.c new file mode 100644 index 0000000000..beb431af8b --- /dev/null +++ b/libmpdemux/aviwrite.c @@ -0,0 +1,172 @@ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "wine/mmreg.h" +#include "wine/avifmt.h" +#include "wine/vfw.h" + +extern char* encode_name; +extern char* encode_index_name; + +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); + +} + + + |