comparison libmpdemux/aviheader.c @ 2310:9e059416eea6

libdemuxer...
author arpi
date Sat, 20 Oct 2001 18:49:08 +0000
parents aviheader.c@3e2a7150cf11
children 8f0861360325
comparison
equal deleted inserted replaced
2309:3128b9d8b4ea 2310:9e059416eea6
1
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5
6 #include "config.h"
7 #include "mp_msg.h"
8
9 #include "stream.h"
10 #include "demuxer.h"
11
12 #include "wine/mmreg.h"
13 #include "wine/avifmt.h"
14 #include "wine/vfw.h"
15
16 #include "codec-cfg.h"
17 #include "bswap.h"
18 #include "stheader.h"
19 #include "aviheader.h"
20
21 #define MIN(a,b) (((a)<(b))?(a):(b))
22
23
24 static MainAVIHeader avih;
25
26 extern void print_avih(MainAVIHeader *h);
27 extern void print_avih_flags(MainAVIHeader *h);
28 extern void print_strh(AVIStreamHeader *h);
29 extern void print_wave_header(WAVEFORMATEX *h);
30 extern void print_video_header(BITMAPINFOHEADER *h);
31 extern void print_index(AVIINDEXENTRY *idx,int idx_size);
32
33 void read_avi_header(demuxer_t *demuxer,int index_mode){
34 sh_audio_t *sh_audio=NULL;
35 sh_video_t *sh_video=NULL;
36 int stream_id=-1;
37 int idxfix_videostream=0;
38 int idxfix_divx=0;
39 avi_priv_t* priv=demuxer->priv;
40
41 //---- AVI header:
42 priv->idx_size=0;
43 while(1){
44 int id=stream_read_dword_le(demuxer->stream);
45 int chunksize,size2;
46 static int last_fccType=0;
47 char* hdr=NULL;
48 //
49 if(stream_eof(demuxer->stream)) break;
50 //
51 if(id==mmioFOURCC('L','I','S','T')){
52 int len=stream_read_dword_le(demuxer->stream)-4; // list size
53 id=stream_read_dword_le(demuxer->stream); // list type
54 mp_msg(MSGT_HEADER,MSGL_DBG2,"LIST %.4s len=%d\n",(char *) &id,len);
55 if(id==listtypeAVIMOVIE){
56 // found MOVI header
57 demuxer->movi_start=stream_tell(demuxer->stream);
58 demuxer->movi_end=demuxer->movi_start+len;
59 mp_msg(MSGT_HEADER,MSGL_V,"Found movie at 0x%X - 0x%X\n",(int)demuxer->movi_start,(int)demuxer->movi_end);
60 if(index_mode==-2) break; // reading from non-seekable source (stdin)
61 len=(len+1)&(~1);
62 stream_skip(demuxer->stream,len);
63 }
64 continue;
65 }
66 size2=stream_read_dword_le(demuxer->stream);
67 mp_msg(MSGT_HEADER,MSGL_DBG2,"CHUNK %.4s len=%d\n",(char *) &id,size2);
68 chunksize=(size2+1)&(~1);
69 switch(id){
70 case mmioFOURCC('I','S','F','T'): hdr="Software";break;
71 case mmioFOURCC('I','N','A','M'): hdr="Name";break;
72 case mmioFOURCC('I','S','B','J'): hdr="Title";break;
73 case mmioFOURCC('I','A','R','T'): hdr="Author";break;
74 case mmioFOURCC('I','C','O','P'): hdr="Copyright";break;
75 case mmioFOURCC('I','C','M','T'): hdr="Comment";break;
76 case ckidAVIMAINHDR: // read 'avih'
77 stream_read(demuxer->stream,(char*) &avih,MIN(size2,sizeof(avih)));
78 le2me_MainAVIHeader(&avih); // swap to machine endian
79 chunksize-=MIN(size2,sizeof(avih));
80 if(verbose) print_avih(&avih); else print_avih_flags(&avih);
81 break;
82 case ckidSTREAMHEADER: { // read 'strh'
83 AVIStreamHeader h;
84 stream_read(demuxer->stream,(char*) &h,MIN(size2,sizeof(h)));
85 le2me_AVIStreamHeader(&h); // swap to machine endian
86 chunksize-=MIN(size2,sizeof(h));
87 ++stream_id;
88 if(h.fccType==streamtypeVIDEO){
89 sh_video=new_sh_video(demuxer,stream_id);
90 memcpy(&sh_video->video,&h,sizeof(h));
91 } else
92 if(h.fccType==streamtypeAUDIO){
93 sh_audio=new_sh_audio(demuxer,stream_id);
94 memcpy(&sh_audio->audio,&h,sizeof(h));
95 }
96 last_fccType=h.fccType;
97 if(verbose>=1) print_strh(&h);
98 break; }
99 case ckidSTREAMFORMAT: { // read 'strf'
100 if(last_fccType==streamtypeVIDEO){
101 sh_video->bih=calloc((chunksize<sizeof(BITMAPINFOHEADER))?sizeof(BITMAPINFOHEADER):chunksize,1);
102 // sh_video->bih=malloc(chunksize); memset(sh_video->bih,0,chunksize);
103 mp_msg(MSGT_HEADER,MSGL_V,"found 'bih', %d bytes of %d\n",chunksize,sizeof(BITMAPINFOHEADER));
104 stream_read(demuxer->stream,(char*) sh_video->bih,chunksize);
105 le2me_BITMAPINFOHEADER(sh_video->bih); // swap to machine endian
106 if(verbose>=1) print_video_header(sh_video->bih);
107 chunksize=0;
108 // sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
109 // sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
110 // if(demuxer->video->id==-1) demuxer->video->id=stream_id;
111 // IdxFix:
112 idxfix_videostream=stream_id;
113 switch(sh_video->bih->biCompression){
114 case mmioFOURCC('D', 'I', 'V', '3'):
115 case mmioFOURCC('d', 'i', 'v', '3'):
116 case mmioFOURCC('D', 'I', 'V', '4'):
117 case mmioFOURCC('d', 'i', 'v', '4'):
118 case mmioFOURCC('D', 'I', 'V', '5'):
119 case mmioFOURCC('d', 'i', 'v', '5'):
120 case mmioFOURCC('D', 'I', 'V', '6'):
121 case mmioFOURCC('d', 'i', 'v', '6'):
122 case mmioFOURCC('M', 'P', '4', '3'):
123 case mmioFOURCC('m', 'p', '4', '3'):
124 case mmioFOURCC('M', 'P', '4', '2'):
125 case mmioFOURCC('m', 'p', '4', '2'):
126 case mmioFOURCC('D', 'I', 'V', '2'):
127 case mmioFOURCC('A', 'P', '4', '1'):
128 idxfix_divx=1; // we can fix keyframes only for divx coded files!
129 }
130 } else
131 if(last_fccType==streamtypeAUDIO){
132 int wf_size = chunksize<sizeof(WAVEFORMATEX)?sizeof(WAVEFORMATEX):chunksize;
133 sh_audio->wf=calloc(wf_size,1);
134 // sh_audio->wf=malloc(chunksize); memset(sh_audio->wf,0,chunksize);
135 mp_msg(MSGT_HEADER,MSGL_V,"found 'wf', %d bytes of %d\n",chunksize,sizeof(WAVEFORMATEX));
136 stream_read(demuxer->stream,(char*) sh_audio->wf,chunksize);
137 le2me_WAVEFORMATEX(sh_audio->wf);
138 if (sh_audio->wf->cbSize != 0 &&
139 wf_size < sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize) {
140 sh_audio->wf=realloc(sh_audio->wf, sizeof(WAVEFORMATEX)+sh_audio->wf->cbSize);
141 }
142 chunksize=0;
143 if(verbose>=1) print_wave_header(sh_audio->wf);
144 // if(demuxer->audio->id==-1) demuxer->audio->id=stream_id;
145 }
146 break;
147 }
148 case ckidAVINEWINDEX: if(index_mode){
149 int i;
150 priv->idx_size=size2>>4;
151 mp_msg(MSGT_HEADER,MSGL_V,"Reading INDEX block, %d chunks for %ld frames\n",
152 priv->idx_size,avih.dwTotalFrames);
153 priv->idx=malloc(priv->idx_size<<4);
154 stream_read(demuxer->stream,(char*)priv->idx,priv->idx_size<<4);
155 for (i = 0; i < priv->idx_size; i++) // swap index to machine endian
156 le2me_AVIINDEXENTRY((AVIINDEXENTRY*)priv->idx + i);
157 chunksize-=priv->idx_size<<4;
158 if(verbose>=2) print_index(priv->idx,priv->idx_size);
159 break;
160 }
161 }
162 if(hdr){
163 char buf[256];
164 int len=(size2<250)?size2:250;
165 stream_read(demuxer->stream,buf,len);
166 chunksize-=len;
167 buf[len]=0;
168 mp_msg(MSGT_HEADER,MSGL_V,"%-10s: %s\n",hdr,buf);
169 }
170 if(chunksize>0) stream_skip(demuxer->stream,chunksize); else
171 if(chunksize<0) mp_msg(MSGT_HEADER,MSGL_WARN,"chunksize=%d (id=%.4s)\n",chunksize,(char *) &id);
172
173 }
174
175 if(index_mode>=2 || (priv->idx_size==0 && index_mode==1)){
176 // build index for file:
177 stream_reset(demuxer->stream);
178 stream_seek(demuxer->stream,demuxer->movi_start);
179
180 priv->idx_pos=0;
181 priv->idx_size=0;
182 priv->idx=NULL;
183
184 while(1){
185 int id,len,skip;
186 AVIINDEXENTRY* idx;
187 unsigned char c;
188 demuxer->filepos=stream_tell(demuxer->stream);
189 if(demuxer->filepos>=demuxer->movi_end) break;
190 id=stream_read_dword_le(demuxer->stream);
191 len=stream_read_dword_le(demuxer->stream);
192 if(id==mmioFOURCC('L','I','S','T')){
193 id=stream_read_dword_le(demuxer->stream); // list type
194 continue;
195 }
196 if(stream_eof(demuxer->stream)) break;
197 if(!id || avi_stream_id(id)==100) goto skip_chunk; // bad ID (or padding?)
198
199 if(priv->idx_pos>=priv->idx_size){
200 // priv->idx_size+=32;
201 priv->idx_size+=1024; // +16kB
202 priv->idx=realloc(priv->idx,priv->idx_size*sizeof(AVIINDEXENTRY));
203 if(!priv->idx){priv->idx_pos=0; break;} // error!
204 }
205 idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
206 idx->ckid=id;
207 idx->dwFlags=AVIIF_KEYFRAME; // FIXME
208 idx->dwChunkOffset=demuxer->filepos;
209 idx->dwChunkLength=len;
210
211 c=stream_read_char(demuxer->stream);
212
213 // Fix keyframes for DivX files:
214 if(idxfix_divx)
215 if(avi_stream_id(id)==idxfix_videostream){
216 if(c&0x40) idx->dwFlags=0;
217 }
218
219 mp_dbg(MSGT_HEADER,MSGL_DBG2,"%08X %08X %.4s %02X %X\n",demuxer->filepos,id,(char *) &id,c,(unsigned int) idx->dwFlags);
220 #if 0
221 { unsigned char tmp[64];
222 int i;
223 stream_read(demuxer->stream,tmp,64);
224 printf("%.4s",&id);
225 for(i=0;i<64;i++) printf(" %02X",tmp[i]);
226 printf("\n");
227 }
228 #endif
229 skip_chunk:
230 skip=(len+1)&(~1); // total bytes in this chunk
231 stream_seek(demuxer->stream,8+demuxer->filepos+skip);
232 }
233 priv->idx_size=priv->idx_pos;
234 mp_msg(MSGT_HEADER,MSGL_INFO,"AVI: Generated index table for %d chunks!\n",priv->idx_size);
235 }
236
237 }
238
239 #undef MIN
240
241