Mercurial > mplayer.hg
comparison demux_avi.c @ 1:3b5f5d1c5041
Initial revision
author | arpi_esp |
---|---|
date | Sat, 24 Feb 2001 20:28:24 +0000 |
parents | |
children | ed4178146cc5 |
comparison
equal
deleted
inserted
replaced
0:c1bb2c071d63 | 1:3b5f5d1c5041 |
---|---|
1 // AVI file parser for DEMUXER v2.6 by A'rpi/ESP-team | |
2 | |
3 //static float avi_pts_frametime=1.0f/25.0f; | |
4 static float avi_audio_pts=0; | |
5 static float avi_video_pts=0; | |
6 | |
7 static int skip_video_frames=0; | |
8 | |
9 static inline int avi_stream_id(unsigned int id){ | |
10 unsigned char *p=(unsigned char *)&id; | |
11 unsigned char a,b; | |
12 a=p[0]-'0'; b=p[1]-'0'; | |
13 if(a>9 || b>9) return 100; // invalid ID | |
14 return a*10+b; | |
15 } | |
16 | |
17 // Select ds from ID | |
18 static inline demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){ | |
19 int stream_id=avi_stream_id(id); | |
20 if(stream_id==demux->audio->id) return demux->audio; | |
21 if(stream_id==demux->video->id) return demux->video; | |
22 if(id!=mmioFOURCC('J','U','N','K')){ | |
23 // unknown | |
24 if(verbose>=2) printf("Unknown chunk: %.4s (%X)\n",&id,id); | |
25 } | |
26 return NULL; | |
27 } | |
28 | |
29 static int demux_avi_read_packet(demuxer_t *demux,unsigned int id,unsigned int len,int idxpos){ | |
30 int d; | |
31 // int len; | |
32 int skip; | |
33 float pts=0; | |
34 unsigned char c=0; | |
35 demux_stream_t *ds=demux_avi_select_stream(demux,id); | |
36 | |
37 if(verbose>=3) printf("demux_avi.read_packet: %X\n",id); | |
38 | |
39 if(ds==demux->audio){ | |
40 pts=avi_audio_pts; | |
41 avi_audio_pts=0; | |
42 } else | |
43 if(ds==demux->video){ | |
44 // video | |
45 if(skip_video_frames>0){ | |
46 // drop frame (seeking) | |
47 --skip_video_frames; | |
48 ds=NULL; | |
49 } else { | |
50 pts=avi_video_pts; | |
51 } | |
52 // ezt a 2 sort lehet hogy fell kell majd cserelni: | |
53 //avi_video_pts+=avi_pts_frametime; | |
54 avi_video_pts+=(float)avi_header.video.dwScale/(float)avi_header.video.dwRate; | |
55 avi_audio_pts=avi_video_pts; | |
56 } | |
57 | |
58 // len=stream_read_dword_le(demux->stream); | |
59 skip=(len+1)&(~1); // total bytes in this chunk | |
60 | |
61 if(ds){ | |
62 if(verbose>=2) printf("DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id); | |
63 ds_read_packet(ds,demux->stream,len,pts,idxpos); | |
64 skip-=len; | |
65 } | |
66 if(skip){ | |
67 if(verbose>=2) printf("DEMUX_AVI: Skipping %d bytes from packet %04X\n",skip,id); | |
68 stream_skip(demux->stream,skip); | |
69 } | |
70 return ds?1:0; | |
71 } | |
72 | |
73 //static int num_elementary_packets100=0; | |
74 //static int num_elementary_packets101=0; | |
75 | |
76 // return value: | |
77 // 0 = EOF or no stream found | |
78 // 1 = successfully read a packet | |
79 int demux_avi_fill_buffer(demuxer_t *demux){ | |
80 unsigned int id=0; | |
81 unsigned int len; | |
82 int skipped=0; | |
83 int max_packs=128; | |
84 int ret=0; | |
85 | |
86 do{ | |
87 AVIINDEXENTRY *idx=NULL; | |
88 demux->filepos=stream_tell(demux->stream); | |
89 if(demux->filepos>=demux->endpos){ | |
90 demux->stream->eof=1; | |
91 return 0; | |
92 } | |
93 if(stream_eof(demux->stream)) return 0; | |
94 if(avi_header.idx_size>0 && avi_header.idx_pos<avi_header.idx_size){ | |
95 unsigned int pos; | |
96 | |
97 //if(avi_header.idx_pos<0) printf("Fatal! idx_pos=%d\n",avi_header.idx_pos); | |
98 | |
99 idx=&avi_header.idx[avi_header.idx_pos++]; | |
100 | |
101 //printf("[%d]",avi_header.idx_pos);fflush(stdout); | |
102 | |
103 //stream_seek(demux->stream,idx.dwChunkOffset); | |
104 //printf("IDX pos=%X idx.pos=%X idx.size=%X idx.flags=%X\n",demux->filepos, | |
105 // pos-4,idx->dwChunkLength,idx->dwFlags); | |
106 if(idx->dwFlags&AVIIF_LIST){ | |
107 // LIST | |
108 continue; | |
109 } | |
110 if(!demux_avi_select_stream(demux,idx->ckid)){ | |
111 if(verbose>2) printf("Skip chunk %.4s (0x%X) \n",&idx->ckid,idx->ckid); | |
112 continue; // skip this chunk | |
113 } | |
114 | |
115 pos=idx->dwChunkOffset+avi_header.idx_offset; | |
116 if(pos<avi_header.movi_start || pos>=avi_header.movi_end){ | |
117 printf("ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos); | |
118 continue; | |
119 } | |
120 #if 0 | |
121 if(pos!=demux->filepos){ | |
122 printf("Warning! pos=0x%X idx.pos=0x%X diff=%d \n",demux->filepos,pos,pos-demux->filepos); | |
123 } | |
124 #endif | |
125 stream_seek(demux->stream,pos); | |
126 id=stream_read_dword_le(demux->stream); | |
127 if(id!=idx->ckid){ | |
128 printf("ChunkID mismatch! raw=%.4s idx=%.4s \n",&id,&idx->ckid); | |
129 continue; | |
130 } | |
131 len=stream_read_dword_le(demux->stream); | |
132 // if((len&(~1))!=(idx->dwChunkLength&(~1))){ | |
133 // if((len)!=(idx->dwChunkLength)){ | |
134 if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){ | |
135 printf("ChunkSize mismatch! raw=%d idx=%d \n",len,idx->dwChunkLength); | |
136 continue; | |
137 } | |
138 } else { | |
139 id=stream_read_dword_le(demux->stream); | |
140 len=stream_read_dword_le(demux->stream); | |
141 if(id==mmioFOURCC('L','I','S','T')){ | |
142 id=stream_read_dword_le(demux->stream); // list type | |
143 continue; | |
144 } | |
145 } | |
146 ret=demux_avi_read_packet(demux,id,len,avi_header.idx_pos-1); | |
147 if(!ret && skip_video_frames<=0) | |
148 if(--max_packs==0){ | |
149 demux->stream->eof=1; | |
150 printf("demux: file doesn't contain the selected audio or video stream\n"); | |
151 return 0; | |
152 } | |
153 } while(ret!=1); | |
154 return 1; | |
155 } | |
156 | |
157 | |
158 // return value: | |
159 // 0 = EOF or no stream found | |
160 // 1 = successfully read a packet | |
161 int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t* ds){ | |
162 unsigned int id=0; | |
163 unsigned int len; | |
164 int skipped=0; | |
165 int max_packs=128; | |
166 int ret=0; | |
167 | |
168 do{ | |
169 AVIINDEXENTRY *idx=NULL; | |
170 int idx_pos=0; | |
171 demux->filepos=stream_tell(demux->stream); | |
172 | |
173 if(ds==demux->video) idx_pos=avi_header.idx_pos_a++; else | |
174 if(ds==demux->audio) idx_pos=avi_header.idx_pos_v++; else | |
175 idx_pos=avi_header.idx_pos++; | |
176 | |
177 if(avi_header.idx_size>0 && idx_pos<avi_header.idx_size){ | |
178 unsigned int pos; | |
179 idx=&avi_header.idx[idx_pos]; | |
180 | |
181 if(idx->dwFlags&AVIIF_LIST){ | |
182 // LIST | |
183 continue; | |
184 } | |
185 if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){ | |
186 if(verbose>2) printf("Skip chunk %.4s (0x%X) \n",&idx->ckid,idx->ckid); | |
187 continue; // skip this chunk | |
188 } | |
189 | |
190 pos=idx->dwChunkOffset+avi_header.idx_offset; | |
191 if(pos<avi_header.movi_start || pos>=avi_header.movi_end){ | |
192 printf("ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos); | |
193 continue; | |
194 } | |
195 #if 0 | |
196 if(pos!=demux->filepos){ | |
197 printf("Warning! pos=0x%X idx.pos=0x%X diff=%d \n",demux->filepos,pos,pos-demux->filepos); | |
198 } | |
199 #endif | |
200 stream_seek(demux->stream,pos); | |
201 | |
202 id=stream_read_dword_le(demux->stream); | |
203 | |
204 if(stream_eof(demux->stream)) return 0; | |
205 | |
206 if(id!=idx->ckid){ | |
207 printf("ChunkID mismatch! raw=%.4s idx=%.4s \n",&id,&idx->ckid); | |
208 continue; | |
209 } | |
210 len=stream_read_dword_le(demux->stream); | |
211 // if((len&(~1))!=(idx->dwChunkLength&(~1))){ | |
212 // if((len)!=(idx->dwChunkLength)){ | |
213 if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){ | |
214 printf("ChunkSize mismatch! raw=%d idx=%d \n",len,idx->dwChunkLength); | |
215 continue; | |
216 } | |
217 } else return 0; | |
218 ret=demux_avi_read_packet(demux,id,len,idx_pos); | |
219 if(!ret && skip_video_frames<=0) | |
220 if(--max_packs==0){ | |
221 demux->stream->eof=1; | |
222 printf("demux: file doesn't contain the selected audio or video stream\n"); | |
223 return 0; | |
224 } | |
225 } while(ret!=1); | |
226 return 1; | |
227 } | |
228 | |
229 | |
230 // return value: | |
231 // 0 = EOF or no stream found | |
232 // 1 = successfully read a packet | |
233 int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t* ds){ | |
234 unsigned int id=0; | |
235 unsigned int len; | |
236 int skipped=0; | |
237 int ret=0; | |
238 int *fpos=NULL; | |
239 | |
240 if(ds==demux->video) fpos=&avi_header.idx_pos_a; else | |
241 if(ds==demux->audio) fpos=&avi_header.idx_pos_v; else | |
242 return 0; | |
243 | |
244 stream_seek(demux->stream,fpos[0]); | |
245 | |
246 do{ | |
247 | |
248 demux->filepos=stream_tell(demux->stream); | |
249 if(demux->filepos>=demux->endpos){ | |
250 demux->stream->eof=1; | |
251 return 0; | |
252 } | |
253 if(stream_eof(demux->stream)) return 0; | |
254 | |
255 id=stream_read_dword_le(demux->stream); | |
256 len=stream_read_dword_le(demux->stream); | |
257 if(id==mmioFOURCC('L','I','S','T')){ | |
258 id=stream_read_dword_le(demux->stream); // list type | |
259 continue; | |
260 } | |
261 | |
262 if(ds==demux_avi_select_stream(demux,id)){ | |
263 // read it! | |
264 ret=demux_avi_read_packet(demux,id,len,avi_header.idx_pos-1); | |
265 } else { | |
266 // skip it! | |
267 int skip=(len+1)&(~1); // total bytes in this chunk | |
268 stream_skip(demux->stream,skip); | |
269 } | |
270 | |
271 } while(ret!=1); | |
272 fpos[0]=stream_tell(demux->stream); | |
273 return 1; | |
274 } | |
275 | |
276 |