Mercurial > mplayer.hg
view libmpdemux/muxer_avi.c @ 9278:caea8ed36b48
The reason why mplayer crashes (in some cases) when using x11
output and -wid (>0) parameter is this:
Mplayer by default creates a colormap using DirectColor visual. If the
window given to mplayer uses TrueColor visual there will be an error
when mplayer sets the colormap for the window. This patch
modifies mplayer to use TrueColor visual if the window given to mplayer
uses TrueColor. Another solution is to make sure that the window given to
mplayer is created using DirectColor visual if it is supported by the
display.
Jouni Tulkki <jitulkki@cc.hut.fi>
author | arpi |
---|---|
date | Tue, 04 Feb 2003 18:31:44 +0000 |
parents | 12fc55eb3373 |
children | e00d3351b912 |
line wrap: on
line source
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <inttypes.h> #include <unistd.h> #include "config.h" #include "../version.h" //#include "stream.h" //#include "demuxer.h" //#include "stheader.h" #include "wine/mmreg.h" #include "wine/avifmt.h" #include "wine/vfw.h" #include "bswap.h" #include "muxer.h" #include "aviheader.h" extern char *info_name; extern char *info_artist; extern char *info_genre; extern char *info_subject; extern char *info_copyright; extern char *info_sourceform; extern char *info_comment; static muxer_stream_t* avifile_new_stream(muxer_t *muxer,int type){ muxer_stream_t* s; if (!muxer) return NULL; if(muxer->avih.dwStreams>=MUXER_MAX_STREAMS){ printf("Too many streams! increase MUXER_MAX_STREAMS !\n"); return NULL; } s=malloc(sizeof(muxer_stream_t)); memset(s,0,sizeof(muxer_stream_t)); if(!s) return NULL; // no mem!? muxer->streams[muxer->avih.dwStreams]=s; s->type=type; s->id=muxer->avih.dwStreams; s->timer=0.0; s->size=0; s->muxer=muxer; switch(type){ case MUXER_TYPE_VIDEO: s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'d','c'); s->h.fccType=streamtypeVIDEO; if(!muxer->def_v) muxer->def_v=s; break; case MUXER_TYPE_AUDIO: s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'w','b'); s->h.fccType=streamtypeAUDIO; break; default: printf("WarninG! unknown stream type: %d\n",type); return NULL; } muxer->avih.dwStreams++; return s; } static void write_avi_chunk(FILE *f,unsigned int id,int len,void* data){ int le_len = le2me_32(len); int le_id = le2me_32(id); fwrite(&le_id,4,1,f); fwrite(&le_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; } } } } static void avifile_write_chunk(muxer_stream_t *s,size_t len,unsigned int flags){ muxer_t *muxer=s->muxer; // add to the index: if(muxer->idx_pos>=muxer->idx_size){ muxer->idx_size+=256; // 4kB muxer->idx=realloc(muxer->idx,16*muxer->idx_size); } muxer->idx[muxer->idx_pos].ckid=s->ckid; muxer->idx[muxer->idx_pos].dwFlags=flags; // keyframe? muxer->idx[muxer->idx_pos].dwChunkOffset=ftell(muxer->file)-(muxer->movi_start-4); muxer->idx[muxer->idx_pos].dwChunkLength=len; ++muxer->idx_pos; // write out the chunk: write_avi_chunk(muxer->file,s->ckid,len,s->buffer); /* unsigned char */ // alter counters: if(s->h.dwSampleSize){ // CBR s->h.dwLength+=len/s->h.dwSampleSize; if(len%s->h.dwSampleSize) printf("Warning! len isn't divisable by samplesize!\n"); } else { // VBR s->h.dwLength++; } s->timer=(double)s->h.dwLength*s->h.dwScale/s->h.dwRate; s->size+=len; if((unsigned int)len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len; } static void write_avi_list(FILE *f,unsigned int id,int len){ unsigned int list_id=FOURCC_LIST; int le_len; int le_id; len+=4; // list fix list_id = le2me_32(list_id); le_len = le2me_32(len); le_id = le2me_32(id); fwrite(&list_id,4,1,f); fwrite(&le_len,4,1,f); fwrite(&le_id,4,1,f); } // muxer->streams[i]->wf->cbSize #define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(((wf)->cbSize)?((wf)->cbSize-2):0)) static void avifile_write_header(muxer_t *muxer){ uint32_t riff[3]; unsigned int i; unsigned int hdrsize; muxer_info_t info[16]; FILE *f=muxer->file; // RIFF header: riff[0]=mmioFOURCC('R','I','F','F'); riff[1]=muxer->file_end-2*sizeof(unsigned int); // filesize riff[2]=formtypeAVI; // 'AVI ' riff[0]=le2me_32(riff[0]); riff[1]=le2me_32(riff[1]); riff[2]=le2me_32(riff[2]); fwrite(&riff,12,1,f); // update AVI header: if(muxer->def_v){ muxer->avih.dwMicroSecPerFrame=1000000.0*muxer->def_v->h.dwScale/muxer->def_v->h.dwRate; // muxer->avih.dwMaxBytesPerSec=1000000; // dummy!!!!! FIXME // muxer->avih.dwPaddingGranularity=2; // ??? muxer->avih.dwFlags|=AVIF_ISINTERLEAVED|AVIF_TRUSTCKTYPE; muxer->avih.dwTotalFrames=muxer->def_v->h.dwLength; // muxer->avih.dwSuggestedBufferSize=muxer->def_v->h.dwSuggestedBufferSize; muxer->avih.dwWidth=muxer->def_v->bih->biWidth; muxer->avih.dwHeight=muxer->def_v->bih->biHeight; } // AVI header: hdrsize=sizeof(muxer->avih)+8; // calc total header size: for(i=0;i<muxer->avih.dwStreams;i++){ hdrsize+=12; // LIST hdrsize+=sizeof(muxer->streams[i]->h)+8; // strh switch(muxer->streams[i]->type){ case MUXER_TYPE_VIDEO: hdrsize+=muxer->streams[i]->bih->biSize+8; // strf break; case MUXER_TYPE_AUDIO: hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf break; } } write_avi_list(f,listtypeAVIHEADER,hdrsize); le2me_MainAVIHeader(&muxer->avih); write_avi_chunk(f,ckidAVIMAINHDR,sizeof(muxer->avih),&muxer->avih); /* MainAVIHeader */ le2me_MainAVIHeader(&muxer->avih); // stream headers: for(i=0;i<muxer->avih.dwStreams;i++){ hdrsize=sizeof(muxer->streams[i]->h)+8; // strh switch(muxer->streams[i]->type){ case MUXER_TYPE_VIDEO: hdrsize+=muxer->streams[i]->bih->biSize+8; // strf break; case MUXER_TYPE_AUDIO: hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf break; } write_avi_list(f,listtypeSTREAMHEADER,hdrsize); le2me_AVIStreamHeader(&muxer->streams[i]->h); write_avi_chunk(f,ckidSTREAMHEADER,sizeof(muxer->streams[i]->h),&muxer->streams[i]->h); /* AVISTreamHeader */ // strh le2me_AVIStreamHeader(&muxer->streams[i]->h); switch(muxer->streams[i]->type){ case MUXER_TYPE_VIDEO: { int biSize=muxer->streams[i]->bih->biSize; le2me_BITMAPINFOHEADER(muxer->streams[i]->bih); write_avi_chunk(f,ckidSTREAMFORMAT,biSize,muxer->streams[i]->bih); /* BITMAPINFOHEADER */ le2me_BITMAPINFOHEADER(muxer->streams[i]->bih); } break; case MUXER_TYPE_AUDIO: { int wfsize = WFSIZE(muxer->streams[i]->wf); le2me_WAVEFORMATEX(muxer->streams[i]->wf); write_avi_chunk(f,ckidSTREAMFORMAT,wfsize,muxer->streams[i]->wf); /* WAVEFORMATEX */ le2me_WAVEFORMATEX(muxer->streams[i]->wf); } break; } } // ============= INFO =============== // always include software info info[0].id=mmioFOURCC('I','S','F','T'); // Software: info[0].text="MEncoder " VERSION; // include any optional strings i=1; if(info_name!=NULL){ info[i].id=mmioFOURCC('I','N','A','M'); // Name: info[i++].text=info_name; } if(info_artist!=NULL){ info[i].id=mmioFOURCC('I','A','R','T'); // Artist: info[i++].text=info_artist; } if(info_genre!=NULL){ info[i].id=mmioFOURCC('I','G','N','R'); // Genre: info[i++].text=info_genre; } if(info_subject!=NULL){ info[i].id=mmioFOURCC('I','S','B','J'); // Subject: info[i++].text=info_subject; } if(info_copyright!=NULL){ info[i].id=mmioFOURCC('I','C','O','P'); // Copyright: info[i++].text=info_copyright; } if(info_sourceform!=NULL){ info[i].id=mmioFOURCC('I','S','R','F'); // Source Form: info[i++].text=info_sourceform; } if(info_comment!=NULL){ info[i].id=mmioFOURCC('I','C','M','T'); // Comment: info[i++].text=info_comment; } info[i].id=0; hdrsize=0; // calc info size: for(i=0;info[i].id!=0;i++) if(info[i].text){ size_t sz=strlen(info[i].text)+1; hdrsize+=sz+8+sz%2; } // write infos: if (hdrsize!=0){ write_avi_list(f,mmioFOURCC('I','N','F','O'),hdrsize); for(i=0;info[i].id!=0;i++) if(info[i].text){ write_avi_chunk(f,info[i].id,strlen(info[i].text)+1,info[i].text); } } // JUNK: write_avi_chunk(f,ckidAVIPADDING,2048-(ftell(f)&2047)-8,NULL); /* junk */ // 'movi' header: write_avi_list(f,listtypeAVIMOVIE,muxer->movi_end-ftell(f)-12); muxer->movi_start=ftell(f); } static void avifile_write_index(muxer_t *muxer){ muxer->movi_end=ftell(muxer->file); if(muxer->idx && muxer->idx_pos>0){ int i; // fixup index entries: // for(i=0;i<muxer->idx_pos;i++) muxer->idx[i].dwChunkOffset-=muxer->movi_start-4; // write index chunk: for (i=0; i<muxer->idx_pos; i++) le2me_AVIINDEXENTRY((&muxer->idx[i])); write_avi_chunk(muxer->file,ckidAVINEWINDEX,16*muxer->idx_pos,muxer->idx); /* AVIINDEXENTRY */ for (i=0; i<muxer->idx_pos; i++) le2me_AVIINDEXENTRY((&muxer->idx[i])); muxer->avih.dwFlags|=AVIF_HASINDEX; } muxer->file_end=ftell(muxer->file); } void muxer_init_muxer_avi(muxer_t *muxer){ muxer->cont_new_stream = &avifile_new_stream; muxer->cont_write_chunk = &avifile_write_chunk; muxer->cont_write_header = &avifile_write_header; muxer->cont_write_index = &avifile_write_index; }