Mercurial > mplayer.hg
annotate libmpdemux/aviwrite.c @ 6969:be2505036de1
New noise filter by Jindrich Makovicka.
Reformatted the paragraph because its column layout completely broke in 80
character displays.
author | diego |
---|---|
date | Sun, 11 Aug 2002 13:37:35 +0000 |
parents | 62ac2cac100d |
children | 4f912998013e |
rev | line source |
---|---|
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
1 |
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
2 #include <stdio.h> |
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
3 #include <stdlib.h> |
2529 | 4 #include <string.h> |
5572
8cd761968f35
BSD-BT848 TV update patch by Charles Henrich <henrich@sigbus.com>
arpi
parents:
2652
diff
changeset
|
5 #include <sys/types.h> |
2529 | 6 |
2555
66837325b929
config.h cleanup, few things added to steram/demuxer headers
arpi
parents:
2529
diff
changeset
|
7 #include "config.h" |
66837325b929
config.h cleanup, few things added to steram/demuxer headers
arpi
parents:
2529
diff
changeset
|
8 |
2529 | 9 //#include "stream.h" |
10 //#include "demuxer.h" | |
11 //#include "stheader.h" | |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
12 |
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
13 #include "wine/mmreg.h" |
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
14 #include "wine/avifmt.h" |
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
15 #include "wine/vfw.h" |
6918 | 16 #include "bswap.h" |
587
8511095c5283
stage#1 completed: c files no more included from mplayer.c
arpi_esp
parents:
1
diff
changeset
|
17 |
2529 | 18 #include "aviwrite.h" |
6918 | 19 #include "aviheader.h" |
1 | 20 |
2529 | 21 aviwrite_stream_t* aviwrite_new_stream(aviwrite_t *muxer,int type){ |
22 aviwrite_stream_t* s; | |
23 if(muxer->avih.dwStreams>=AVIWRITE_MAX_STREAMS){ | |
24 printf("Too many streams! increase AVIWRITE_MAX_STREAMS !\n"); | |
25 return NULL; | |
26 } | |
27 s=malloc(sizeof(aviwrite_stream_t)); | |
28 memset(s,0,sizeof(aviwrite_stream_t)); | |
29 if(!s) return NULL; // no mem!? | |
30 muxer->streams[muxer->avih.dwStreams]=s; | |
31 s->type=type; | |
32 s->id=muxer->avih.dwStreams; | |
33 s->timer=0.0; | |
2652 | 34 s->size=0; |
2529 | 35 switch(type){ |
36 case AVIWRITE_TYPE_VIDEO: | |
37 s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'d','c'); | |
38 s->h.fccType=streamtypeVIDEO; | |
39 if(!muxer->def_v) muxer->def_v=s; | |
40 break; | |
41 case AVIWRITE_TYPE_AUDIO: | |
42 s->ckid=mmioFOURCC(('0'+s->id/10),('0'+(s->id%10)),'w','b'); | |
43 s->h.fccType=streamtypeAUDIO; | |
44 break; | |
45 default: | |
46 printf("WarninG! unknown stream type: %d\n",type); | |
47 return NULL; | |
48 } | |
49 muxer->avih.dwStreams++; | |
50 return s; | |
51 } | |
1 | 52 |
2529 | 53 aviwrite_t* aviwrite_new_muxer(){ |
54 aviwrite_t* muxer=malloc(sizeof(aviwrite_t)); | |
55 memset(muxer,0,sizeof(aviwrite_t)); | |
56 return muxer; | |
57 } | |
58 | |
59 static void write_avi_chunk(FILE *f,unsigned int id,int len,void* data){ | |
6918 | 60 int le_len = le2me_32(len); |
61 int le_id = le2me_32(id); | |
62 fwrite(&le_id,4,1,f); | |
63 fwrite(&le_len,4,1,f); | |
64 | |
1 | 65 if(len>0){ |
66 if(data){ | |
67 // DATA | |
68 fwrite(data,len,1,f); | |
69 if(len&1){ // padding | |
70 unsigned char zerobyte=0; | |
71 fwrite(&zerobyte,1,1,f); | |
72 } | |
73 } else { | |
74 // JUNK | |
75 char *avi_junk_data="[= MPlayer junk data! =]"; | |
76 if(len&1) ++len; // padding | |
77 while(len>0){ | |
78 int l=strlen(avi_junk_data); | |
79 if(l>len) l=len; | |
80 fwrite(avi_junk_data,l,1,f); | |
81 len-=l; | |
82 } | |
83 } | |
84 } | |
2529 | 85 } |
86 | |
87 void aviwrite_write_chunk(aviwrite_t *muxer,aviwrite_stream_t *s, FILE *f,int len,unsigned int flags){ | |
88 | |
89 // add to the index: | |
90 if(muxer->idx_pos>=muxer->idx_size){ | |
91 muxer->idx_size+=256; // 4kB | |
92 muxer->idx=realloc(muxer->idx,16*muxer->idx_size); | |
93 } | |
94 muxer->idx[muxer->idx_pos].ckid=s->ckid; | |
95 muxer->idx[muxer->idx_pos].dwFlags=flags; // keyframe? | |
96 muxer->idx[muxer->idx_pos].dwChunkOffset=ftell(f)-(muxer->movi_start-4); | |
97 muxer->idx[muxer->idx_pos].dwChunkLength=len; | |
98 ++muxer->idx_pos; | |
99 | |
100 // write out the chunk: | |
6918 | 101 write_avi_chunk(f,s->ckid,len,s->buffer); /* unsigned char */ |
102 | |
2529 | 103 // alter counters: |
104 if(s->h.dwSampleSize){ | |
105 // CBR | |
106 s->h.dwLength+=len/s->h.dwSampleSize; | |
107 if(len%s->h.dwSampleSize) printf("Warning! len isn't divisable by samplesize!\n"); | |
108 } else { | |
109 // VBR | |
110 s->h.dwLength++; | |
111 } | |
112 s->timer=(double)s->h.dwLength*s->h.dwScale/s->h.dwRate; | |
2652 | 113 s->size+=len; |
2529 | 114 if(len>s->h.dwSuggestedBufferSize) s->h.dwSuggestedBufferSize=len; |
1 | 115 |
116 } | |
117 | |
2529 | 118 static void write_avi_list(FILE *f,unsigned int id,int len){ |
1 | 119 unsigned int list_id=FOURCC_LIST; |
6918 | 120 int le_len; |
121 int le_id; | |
1 | 122 len+=4; // list fix |
6918 | 123 list_id = le2me_32(list_id); |
124 le_len = le2me_32(len); | |
125 le_id = le2me_32(id); | |
1 | 126 fwrite(&list_id,4,1,f); |
6918 | 127 fwrite(&le_len,4,1,f); |
128 fwrite(&le_id,4,1,f); | |
1 | 129 } |
130 | |
2635
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
131 // muxer->streams[i]->wf->cbSize |
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
132 #define WFSIZE(wf) (sizeof(WAVEFORMATEX)+(((wf)->cbSize)?((wf)->cbSize-2):0)) |
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
133 |
2529 | 134 void aviwrite_write_header(aviwrite_t *muxer,FILE *f){ |
1 | 135 unsigned int riff[3]; |
2529 | 136 int i; |
137 unsigned int hdrsize; | |
1 | 138 // RIFF header: |
6918 | 139 #ifdef WORDS_BIGENDIAN |
140 /* FIXME: updating the header on big-endian causes the video | |
141 * to be unreadable ("AVI_NI: No video stream found!"). | |
142 * Just don't update it (no seeking, not playable with WMP, | |
143 * but better than nothing) | |
144 */ | |
145 if(muxer->file_end != 0) | |
146 return; | |
147 #endif | |
1 | 148 riff[0]=mmioFOURCC('R','I','F','F'); |
2529 | 149 riff[1]=muxer->file_end; // filesize |
1 | 150 riff[2]=formtypeAVI; // 'AVI ' |
6918 | 151 riff[0]=le2me_32(riff[0]); |
152 riff[1]=le2me_32(riff[1]); | |
153 riff[2]=le2me_32(riff[2]); | |
1 | 154 fwrite(&riff,12,1,f); |
2529 | 155 // update AVI header: |
156 if(muxer->def_v){ | |
157 muxer->avih.dwMicroSecPerFrame=1000000.0*muxer->def_v->h.dwScale/muxer->def_v->h.dwRate; | |
2635
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
158 // muxer->avih.dwMaxBytesPerSec=1000000; // dummy!!!!! FIXME |
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
159 // muxer->avih.dwPaddingGranularity=2; // ??? |
2529 | 160 muxer->avih.dwFlags|=AVIF_ISINTERLEAVED|AVIF_TRUSTCKTYPE; |
161 muxer->avih.dwTotalFrames=muxer->def_v->h.dwLength; | |
2635
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
162 // muxer->avih.dwSuggestedBufferSize=muxer->def_v->h.dwSuggestedBufferSize; |
2529 | 163 muxer->avih.dwWidth=muxer->def_v->bih->biWidth; |
164 muxer->avih.dwHeight=muxer->def_v->bih->biHeight; | |
165 } | |
166 | |
1 | 167 // AVI header: |
2529 | 168 hdrsize=sizeof(muxer->avih)+8; |
169 // calc total header size: | |
170 for(i=0;i<muxer->avih.dwStreams;i++){ | |
171 hdrsize+=12; // LIST | |
172 hdrsize+=sizeof(muxer->streams[i]->h)+8; // strh | |
173 switch(muxer->streams[i]->type){ | |
174 case AVIWRITE_TYPE_VIDEO: | |
175 hdrsize+=muxer->streams[i]->bih->biSize+8; // strf | |
176 break; | |
177 case AVIWRITE_TYPE_AUDIO: | |
2635
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
178 hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf |
2529 | 179 break; |
180 } | |
181 } | |
182 write_avi_list(f,listtypeAVIHEADER,hdrsize); | |
6918 | 183 |
184 le2me_MainAVIHeader(&muxer->avih); | |
185 write_avi_chunk(f,ckidAVIMAINHDR,sizeof(muxer->avih),&muxer->avih); /* MainAVIHeader */ | |
186 le2me_MainAVIHeader(&muxer->avih); | |
2529 | 187 |
188 // stream headers: | |
189 for(i=0;i<muxer->avih.dwStreams;i++){ | |
190 hdrsize=sizeof(muxer->streams[i]->h)+8; // strh | |
191 switch(muxer->streams[i]->type){ | |
192 case AVIWRITE_TYPE_VIDEO: | |
193 hdrsize+=muxer->streams[i]->bih->biSize+8; // strf | |
194 break; | |
195 case AVIWRITE_TYPE_AUDIO: | |
2635
c1e24e01601b
fixed AVI header creation - now should be compatible with NaNdub
arpi
parents:
2555
diff
changeset
|
196 hdrsize+=WFSIZE(muxer->streams[i]->wf)+8; // strf |
2529 | 197 break; |
198 } | |
199 write_avi_list(f,listtypeSTREAMHEADER,hdrsize); | |
6918 | 200 le2me_AVIStreamHeader(&muxer->streams[i]->h); |
201 write_avi_chunk(f,ckidSTREAMHEADER,sizeof(muxer->streams[i]->h),&muxer->streams[i]->h); /* AVISTreamHeader */ // strh | |
202 le2me_AVIStreamHeader(&muxer->streams[i]->h); | |
203 | |
2529 | 204 switch(muxer->streams[i]->type){ |
205 case AVIWRITE_TYPE_VIDEO: | |
6918 | 206 { |
207 int biSize=muxer->streams[i]->bih->biSize; | |
208 le2me_BITMAPINFOHEADER(muxer->streams[i]->bih); | |
209 write_avi_chunk(f,ckidSTREAMFORMAT,biSize,muxer->streams[i]->bih); /* BITMAPINFOHEADER */ | |
210 le2me_BITMAPINFOHEADER(muxer->streams[i]->bih); | |
211 } | |
2529 | 212 break; |
213 case AVIWRITE_TYPE_AUDIO: | |
6918 | 214 { |
215 int wfsize = WFSIZE(muxer->streams[i]->wf); | |
216 le2me_WAVEFORMATEX(muxer->streams[i]->wf); | |
217 write_avi_chunk(f,ckidSTREAMFORMAT,wfsize,muxer->streams[i]->wf); /* WAVEFORMATEX */ | |
218 le2me_WAVEFORMATEX(muxer->streams[i]->wf); | |
219 } | |
2529 | 220 break; |
221 } | |
222 } | |
223 | |
224 // JUNK: | |
6918 | 225 write_avi_chunk(f,ckidAVIPADDING,2048-(ftell(f)&2047)-8,NULL); /* junk */ |
1 | 226 // 'movi' header: |
2529 | 227 write_avi_list(f,listtypeAVIMOVIE,muxer->movi_end-ftell(f)-12); |
228 muxer->movi_start=ftell(f); | |
1 | 229 } |
230 | |
2529 | 231 void aviwrite_write_index(aviwrite_t *muxer,FILE *f){ |
232 muxer->movi_end=ftell(f); | |
233 if(muxer->idx && muxer->idx_pos>0){ | |
6918 | 234 int i; |
2529 | 235 // fixup index entries: |
236 // for(i=0;i<muxer->idx_pos;i++) muxer->idx[i].dwChunkOffset-=muxer->movi_start-4; | |
237 // write index chunk: | |
6918 | 238 for (i=0; i<muxer->idx_pos; i++) le2me_AVIINDEXENTRY((&muxer->idx[i])); |
239 write_avi_chunk(f,ckidAVINEWINDEX,16*muxer->idx_pos,muxer->idx); /* AVIINDEXENTRY */ | |
240 for (i=0; i<muxer->idx_pos; i++) le2me_AVIINDEXENTRY((&muxer->idx[i])); | |
2529 | 241 muxer->avih.dwFlags|=AVIF_HASINDEX; |
242 } | |
243 muxer->file_end=ftell(f); | |
1 | 244 } |
245 |