comparison demux_avi.c @ 1485:b895f95e7657

AVI demuxer cleanups, fileformat-dependent stuff moved to priv_t
author arpi
date Sat, 11 Aug 2001 20:37:33 +0000
parents db2a6ae7e296
children 8c3e93ef116d
comparison
equal deleted inserted replaced
1484:14af3106c359 1485:b895f95e7657
1 // AVI file parser for DEMUXER v2.6 by A'rpi/ESP-team 1 // AVI file parser for DEMUXER v2.9 by A'rpi/ESP-team
2 2
3 #include <stdio.h> 3 #include <stdio.h>
4 #include <stdlib.h> 4 #include <stdlib.h>
5 #include <unistd.h> 5 #include <unistd.h>
6 6
14 #include "wine/vfw.h" 14 #include "wine/vfw.h"
15 15
16 #include "codec-cfg.h" 16 #include "codec-cfg.h"
17 #include "stheader.h" 17 #include "stheader.h"
18 18
19 //static float avi_pts_frametime=1.0f/25.0f; 19 #include "aviheader.h"
20 float avi_audio_pts=0;
21 float avi_video_pts=0;
22 //float avi_video_ftime=0.04;
23 int skip_video_frames=0;
24 20
25 // Select ds from ID 21 // Select ds from ID
26 demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){ 22 demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){
27 int stream_id=avi_stream_id(id); 23 int stream_id=avi_stream_id(id);
28 24
56 if(verbose>=2) printf("Unknown chunk: %.4s (%X)\n",(char *) &id,id); 52 if(verbose>=2) printf("Unknown chunk: %.4s (%X)\n",(char *) &id,id);
57 } 53 }
58 return NULL; 54 return NULL;
59 } 55 }
60 56
61 static float pts_correction=0.0;
62 static int pts_corrected=0;
63 static int pts_has_video=0;
64 static unsigned int pts_corr_bytes=0;
65 57
66 static int demux_avi_read_packet(demuxer_t *demux,unsigned int id,unsigned int len,int idxpos,int flags){ 58 static int demux_avi_read_packet(demuxer_t *demux,unsigned int id,unsigned int len,int idxpos,int flags){
59 avi_priv_t *priv=demux->priv;
67 int skip; 60 int skip;
68 float pts=0; 61 float pts=0;
69 demux_stream_t *ds=demux_avi_select_stream(demux,id); 62 demux_stream_t *ds=demux_avi_select_stream(demux,id);
70 63
71 if(verbose>=3) printf("demux_avi.read_packet: %X\n",id); 64 if(verbose>=3) printf("demux_avi.read_packet: %X\n",id);
72 65
73 if(ds==demux->audio){ 66 if(ds==demux->audio){
74 67
75 if(pts_corrected==0){ 68 if(priv->pts_corrected==0){
76 // printf("\rYYY-A A: %5.3f V: %5.3f \n",avi_audio_pts,avi_video_pts); 69 // printf("\rYYY-A A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts);
77 if(pts_has_video){ 70 if(priv->pts_has_video){
78 // we have video pts now 71 // we have video pts now
79 float delay=(float)pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec; 72 float delay=(float)priv->pts_corr_bytes/((sh_audio_t*)(ds->sh))->wf->nAvgBytesPerSec;
80 printf("XXX initial v_pts=%5.3f a_pos=%d (%5.3f) \n",avi_audio_pts,pts_corr_bytes,delay); 73 printf("XXX initial v_pts=%5.3f a_pos=%d (%5.3f) \n",priv->avi_audio_pts,priv->pts_corr_bytes,delay);
81 //pts_correction=-avi_audio_pts+delay; 74 //priv->pts_correction=-priv->avi_audio_pts+delay;
82 pts_correction=delay-avi_audio_pts; 75 priv->pts_correction=delay-priv->avi_audio_pts;
83 avi_audio_pts+=pts_correction; 76 priv->avi_audio_pts+=priv->pts_correction;
84 pts_corrected=1; 77 priv->pts_corrected=1;
85 } else 78 } else
86 pts_corr_bytes+=len; 79 priv->pts_corr_bytes+=len;
87 } 80 }
88 pts=avi_audio_pts; //+pts_correction; 81 pts=priv->avi_audio_pts; //+priv->pts_correction;
89 avi_audio_pts=0; 82 priv->avi_audio_pts=0;
90 } else 83 } else
91 if(ds==demux->video){ 84 if(ds==demux->video){
92 // video 85 // video
93 if(skip_video_frames>0){ 86 if(priv->skip_video_frames>0){
94 // drop frame (seeking) 87 // drop frame (seeking)
95 --skip_video_frames; 88 --priv->skip_video_frames;
96 ds=NULL; 89 ds=NULL;
97 } else { 90 } else {
98 pts=avi_video_pts; 91 pts=priv->avi_video_pts;
99 } 92 }
100 // ezt a 2 sort lehet hogy fell kell majd cserelni: 93 // ezt a 2 sort lehet hogy fell kell majd cserelni:
101 //avi_video_pts+=avi_pts_frametime; 94 //priv->avi_video_pts+=avi_pts_frametime;
102 //avi_video_pts+=(float)avi_header.video.dwScale/(float)avi_header.video.dwRate; 95 //priv->avi_video_pts+=(float)avi_header.video.dwScale/(float)avi_header.video.dwRate;
103 //avi_video_pts+=((sh_video_t*)ds->sh)->frametime; 96 //priv->avi_video_pts+=((sh_video_t*)ds->sh)->frametime;
104 // FIXME!!! 97 // FIXME!!!
105 #if 1 98 #if 1
106 // printf("ds=0x%X\n",ds); 99 // printf("ds=0x%X\n",ds);
107 // printf("packno=%d\n",ds->pack_no); 100 // printf("packno=%d\n",ds->pack_no);
108 // printf("### pack_no=%d\n",demux->video->pack_no+demux->video->packs); 101 // printf("### pack_no=%d\n",demux->video->pack_no+demux->video->packs);
109 avi_video_pts = (demux->video->pack_no+demux->video->packs) * 102 priv->avi_video_pts = (demux->video->pack_no+demux->video->packs) *
110 (float)((sh_video_t*)demux->video->sh)->video.dwScale / 103 (float)((sh_video_t*)demux->video->sh)->video.dwScale /
111 (float)((sh_video_t*)demux->video->sh)->video.dwRate; 104 (float)((sh_video_t*)demux->video->sh)->video.dwRate;
112 #else 105 #else
113 avi_video_pts+=(float)((sh_video_t*)(demux->video->sh))->video.dwScale/(float)((sh_video_t*)(demux->video->sh))->video.dwRate; 106 priv->avi_video_pts+=(float)((sh_video_t*)(demux->video->sh))->video.dwScale/(float)((sh_video_t*)(demux->video->sh))->video.dwRate;
114 // avi_video_pts+=avi_video_ftime; 107 // priv->avi_video_pts+=avi_video_ftime;
115 #endif 108 #endif
116 // printf("\rYYY-V A: %5.3f V: %5.3f \n",avi_audio_pts,avi_video_pts); 109 // printf("\rYYY-V A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts);
117 avi_audio_pts=avi_video_pts+pts_correction; 110 priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction;
118 pts_has_video=1; 111 priv->pts_has_video=1;
119 112
120 } 113 }
121 114
122 // len=stream_read_dword_le(demux->stream); 115 // len=stream_read_dword_le(demux->stream);
123 skip=(len+1)&(~1); // total bytes in this chunk 116 skip=(len+1)&(~1); // total bytes in this chunk
132 stream_skip(demux->stream,skip); 125 stream_skip(demux->stream,skip);
133 } 126 }
134 return ds?1:0; 127 return ds?1:0;
135 } 128 }
136 129
137 //static int num_elementary_packets100=0;
138 //static int num_elementary_packets101=0;
139
140 // return value: 130 // return value:
141 // 0 = EOF or no stream found 131 // 0 = EOF or no stream found
142 // 1 = successfully read a packet 132 // 1 = successfully read a packet
143 int demux_avi_fill_buffer(demuxer_t *demux){ 133 int demux_avi_fill_buffer(demuxer_t *demux){
134 avi_priv_t *priv=demux->priv;
144 unsigned int id=0; 135 unsigned int id=0;
145 unsigned int len; 136 unsigned int len;
146 int max_packs=128; 137 int max_packs=128;
147 int ret=0; 138 int ret=0;
148 139
155 demux->stream->eof=1; 146 demux->stream->eof=1;
156 return 0; 147 return 0;
157 } 148 }
158 if(stream_eof(demux->stream)) return 0; 149 if(stream_eof(demux->stream)) return 0;
159 #endif 150 #endif
160 if(demux->idx_size>0 && demux->idx_pos<demux->idx_size){ 151 if(priv->idx_size>0 && priv->idx_pos<priv->idx_size){
161 unsigned int pos; 152 unsigned int pos;
162 153
163 //if(demux->idx_pos<0) printf("Fatal! idx_pos=%d\n",demux->idx_pos); 154 //if(priv->idx_pos<0) printf("Fatal! idx_pos=%d\n",priv->idx_pos);
164 155
165 idx=&((AVIINDEXENTRY *)demux->idx)[demux->idx_pos++]; 156 idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
166 157
167 //printf("[%d]",demux->idx_pos);fflush(stdout); 158 //printf("[%d]",priv->idx_pos);fflush(stdout);
168 159
169 //stream_seek(demux->stream,idx.dwChunkOffset); 160 //stream_seek(demux->stream,idx.dwChunkOffset);
170 //printf("IDX pos=%X idx.pos=%X idx.size=%X idx.flags=%X\n",demux->filepos, 161 //printf("IDX pos=%X idx.pos=%X idx.size=%X idx.flags=%X\n",demux->filepos,
171 // pos-4,idx->dwChunkLength,idx->dwFlags); 162 // pos-4,idx->dwChunkLength,idx->dwFlags);
172 if(idx->dwFlags&AVIIF_LIST){ 163 if(idx->dwFlags&AVIIF_LIST){
176 if(!demux_avi_select_stream(demux,idx->ckid)){ 167 if(!demux_avi_select_stream(demux,idx->ckid)){
177 if(verbose>2) printf("Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid); 168 if(verbose>2) printf("Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid);
178 continue; // skip this chunk 169 continue; // skip this chunk
179 } 170 }
180 171
181 pos=idx->dwChunkOffset+demux->idx_offset; 172 pos=idx->dwChunkOffset+priv->idx_offset;
182 if(pos<demux->movi_start || pos>=demux->movi_end){ 173 if(pos<demux->movi_start || pos>=demux->movi_end){
183 printf("ChunkOffset out of range! idx=0x%X \n",pos); 174 printf("ChunkOffset out of range! idx=0x%X \n",pos);
184 continue; 175 continue;
185 } 176 }
186 #if 0 177 #if 0
220 if(id==mmioFOURCC('L','I','S','T')){ 211 if(id==mmioFOURCC('L','I','S','T')){
221 id=stream_read_dword_le(demux->stream); // list type 212 id=stream_read_dword_le(demux->stream); // list type
222 continue; 213 continue;
223 } 214 }
224 } 215 }
225 ret=demux_avi_read_packet(demux,id,len,demux->idx_pos-1,flags); 216 ret=demux_avi_read_packet(demux,id,len,priv->idx_pos-1,flags);
226 if(!ret && skip_video_frames<=0) 217 if(!ret && priv->skip_video_frames<=0)
227 if(--max_packs==0){ 218 if(--max_packs==0){
228 demux->stream->eof=1; 219 demux->stream->eof=1;
229 printf("demux: file doesn't contain the selected audio or video stream\n"); 220 printf("demux: file doesn't contain the selected audio or video stream\n");
230 return 0; 221 return 0;
231 } 222 }
236 227
237 // return value: 228 // return value:
238 // 0 = EOF or no stream found 229 // 0 = EOF or no stream found
239 // 1 = successfully read a packet 230 // 1 = successfully read a packet
240 int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t* ds){ 231 int demux_avi_fill_buffer_ni(demuxer_t *demux,demux_stream_t* ds){
232 avi_priv_t *priv=demux->priv;
241 unsigned int id=0; 233 unsigned int id=0;
242 unsigned int len; 234 unsigned int len;
243 int max_packs=128; 235 int max_packs=128;
244 int ret=0; 236 int ret=0;
245 237
247 int flags=0; 239 int flags=0;
248 AVIINDEXENTRY *idx=NULL; 240 AVIINDEXENTRY *idx=NULL;
249 int idx_pos=0; 241 int idx_pos=0;
250 demux->filepos=stream_tell(demux->stream); 242 demux->filepos=stream_tell(demux->stream);
251 243
252 if(ds==demux->video) idx_pos=demux->idx_pos_v++; else 244 if(ds==demux->video) idx_pos=priv->idx_pos_v++; else
253 if(ds==demux->audio) idx_pos=demux->idx_pos_a++; else 245 if(ds==demux->audio) idx_pos=priv->idx_pos_a++; else
254 idx_pos=demux->idx_pos++; 246 idx_pos=priv->idx_pos++;
255 247
256 if(demux->idx_size>0 && idx_pos<demux->idx_size){ 248 if(priv->idx_size>0 && idx_pos<priv->idx_size){
257 unsigned int pos; 249 unsigned int pos;
258 idx=&((AVIINDEXENTRY *)demux->idx)[idx_pos]; 250 idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos];
259 // idx=&demux->idx[idx_pos]; 251 // idx=&priv->idx[idx_pos];
260 252
261 if(idx->dwFlags&AVIIF_LIST){ 253 if(idx->dwFlags&AVIIF_LIST){
262 // LIST 254 // LIST
263 continue; 255 continue;
264 } 256 }
265 if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){ 257 if(ds && demux_avi_select_stream(demux,idx->ckid)!=ds){
266 if(verbose>2) printf("Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid); 258 if(verbose>2) printf("Skip chunk %.4s (0x%X) \n",(char *)&idx->ckid,(unsigned int)idx->ckid);
267 continue; // skip this chunk 259 continue; // skip this chunk
268 } 260 }
269 261
270 pos=idx->dwChunkOffset+demux->idx_offset; 262 pos=idx->dwChunkOffset+priv->idx_offset;
271 if(pos<demux->movi_start || pos>=demux->movi_end){ 263 if(pos<demux->movi_start || pos>=demux->movi_end){
272 printf("ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos); 264 printf("ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos);
273 continue; 265 continue;
274 } 266 }
275 #if 0 267 #if 0
297 // continue; 289 // continue;
298 } 290 }
299 if(idx->dwFlags&AVIIF_KEYFRAME) flags=1; 291 if(idx->dwFlags&AVIIF_KEYFRAME) flags=1;
300 } else return 0; 292 } else return 0;
301 ret=demux_avi_read_packet(demux,id,len,idx_pos,flags); 293 ret=demux_avi_read_packet(demux,id,len,idx_pos,flags);
302 if(!ret && skip_video_frames<=0) 294 if(!ret && priv->skip_video_frames<=0)
303 if(--max_packs==0){ 295 if(--max_packs==0){
304 demux->stream->eof=1; 296 demux->stream->eof=1;
305 printf("demux: file doesn't contain the selected audio or video stream\n"); 297 printf("demux: file doesn't contain the selected audio or video stream\n");
306 return 0; 298 return 0;
307 } 299 }
312 304
313 // return value: 305 // return value:
314 // 0 = EOF or no stream found 306 // 0 = EOF or no stream found
315 // 1 = successfully read a packet 307 // 1 = successfully read a packet
316 int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t* ds){ 308 int demux_avi_fill_buffer_nini(demuxer_t *demux,demux_stream_t* ds){
309 avi_priv_t *priv=demux->priv;
317 unsigned int id=0; 310 unsigned int id=0;
318 unsigned int len; 311 unsigned int len;
319 int ret=0; 312 int ret=0;
320 int *fpos=NULL; 313 int *fpos=NULL;
321 314
322 if(ds==demux->video) fpos=&demux->idx_pos_v; else 315 if(ds==demux->video) fpos=&priv->idx_pos_v; else
323 if(ds==demux->audio) fpos=&demux->idx_pos_a; else 316 if(ds==demux->audio) fpos=&priv->idx_pos_a; else
324 return 0; 317 return 0;
325 318
326 stream_seek(demux->stream,fpos[0]); 319 stream_seek(demux->stream,fpos[0]);
327 320
328 do{ 321 do{
341 continue; 334 continue;
342 } 335 }
343 336
344 if(ds==demux_avi_select_stream(demux,id)){ 337 if(ds==demux_avi_select_stream(demux,id)){
345 // read it! 338 // read it!
346 ret=demux_avi_read_packet(demux,id,len,demux->idx_pos-1,0); 339 ret=demux_avi_read_packet(demux,id,len,priv->idx_pos-1,0);
347 } else { 340 } else {
348 // skip it! 341 // skip it!
349 int skip=(len+1)&(~1); // total bytes in this chunk 342 int skip=(len+1)&(~1); // total bytes in this chunk
350 stream_skip(demux->stream,skip); 343 stream_skip(demux->stream,skip);
351 } 344 }
353 } while(ret!=1); 346 } while(ret!=1);
354 fpos[0]=stream_tell(demux->stream); 347 fpos[0]=stream_tell(demux->stream);
355 return 1; 348 return 1;
356 } 349 }
357 350
358 extern float initial_pts_delay; 351 extern int audio_id;
352 extern int video_id;
353 extern int index_mode; // -1=untouched 0=don't use index 1=use (geneate) index
354 extern int force_ni;
355 extern int pts_from_bps;
356
357 demuxer_t* demux_open_avi(demuxer_t* demuxer){
358 demux_stream_t *d_audio=demuxer->audio;
359 demux_stream_t *d_video=demuxer->video;
360 sh_audio_t *sh_audio=NULL;
361 sh_video_t *sh_video=NULL;
362 avi_priv_t* priv=malloc(sizeof(avi_priv_t));
363
364 // priv struct:
365 priv->avi_audio_pts=priv->avi_video_pts=0.0f;
366 priv->pts_correction=0.0f;
367 priv->skip_video_frames=0;
368 priv->pts_corr_bytes=0;
369 priv->pts_has_video=priv->pts_corrected=0;
370 demuxer->priv=(void*)priv;
371
372 //---- AVI header:
373 read_avi_header(demuxer,(demuxer->stream->type!=STREAMTYPE_STREAM)?index_mode:-2);
374 stream_reset(demuxer->stream);
375 stream_seek(demuxer->stream,demuxer->movi_start);
376 priv->idx_pos=0;
377 priv->idx_pos_a=0;
378 priv->idx_pos_v=0;
379 if(priv->idx_size>0){
380 // decide index format:
381 if(((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset<demuxer->movi_start)
382 priv->idx_offset=demuxer->movi_start-4;
383 else
384 priv->idx_offset=0;
385 if(verbose) printf("AVI index offset: %d\n",priv->idx_offset);
386 }
387 // demuxer->endpos=avi_header.movi_end;
388
389 if(priv->idx_size>0){
390 // check that file is non-interleaved:
391 int i;
392 int a_pos=-1;
393 int v_pos=-1;
394 for(i=0;i<priv->idx_size;i++){
395 AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)priv->idx)[i];
396 demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
397 int pos=idx->dwChunkOffset+priv->idx_offset;
398 if(a_pos==-1 && ds==demuxer->audio){
399 a_pos=pos;
400 if(v_pos!=-1) break;
401 }
402 if(v_pos==-1 && ds==demuxer->video){
403 v_pos=pos;
404 if(a_pos!=-1) break;
405 }
406 }
407 if(v_pos==-1){
408 fprintf(stderr,"AVI_NI: missing video stream!? contact the author, it may be a bug :(\n");
409 return NULL;
410 // GUI_MSG( mplErrorAVINI )
411 // exit(1);
412 }
413 if(a_pos==-1){
414 printf("AVI_NI: No audio stream found -> nosound\n");
415 sh_audio=NULL;
416 } else {
417 if(force_ni || abs(a_pos-v_pos)>0x100000){ // distance > 1MB
418 printf("%s NON-INTERLEAVED AVI file-format!\n",force_ni?"Forced":"Detected");
419 demuxer->type=DEMUXER_TYPE_AVI_NI; // HACK!!!!
420 pts_from_bps=1; // force BPS sync!
421 }
422 }
423 } else {
424 // no index
425 if(force_ni){
426 printf("Using NON-INTERLEAVED Broken AVI file-format!\n");
427 demuxer->type=DEMUXER_TYPE_AVI_NINI; // HACK!!!!
428 priv->idx_pos_a=
429 priv->idx_pos_v=demuxer->movi_start;
430 pts_from_bps=1; // force BPS sync!
431 }
432 }
433 if(!ds_fill_buffer(d_video)){
434 fprintf(stderr,"AVI: missing video stream!? contact the author, it may be a bug :(\n");
435 return NULL;
436 // GUI_MSG( mplAVIErrorMissingVideoStream )
437 // exit(1);
438 }
439 sh_video=d_video->sh;sh_video->ds=d_video;
440 if(audio_id!=-2){
441 if(verbose) printf("AVI: Searching for audio stream (id:%d)\n",d_audio->id);
442 if(!ds_fill_buffer(d_audio)){
443 printf("AVI: No Audio stream found... ->nosound\n");
444 sh_audio=NULL;
445 } else {
446 sh_audio=d_audio->sh;sh_audio->ds=d_audio;
447 sh_audio->format=sh_audio->wf->wFormatTag;
448 }
449 }
450 // calc. FPS:
451 sh_video->fps=(float)sh_video->video.dwRate/(float)sh_video->video.dwScale;
452 sh_video->frametime=(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
453 // calculating video bitrate:
454 sh_video->i_bps=demuxer->movi_end-demuxer->movi_start-priv->idx_size*8;
455 if(sh_audio) sh_video->i_bps-=sh_audio->audio.dwLength;
456 if(verbose) printf("AVI video length=%d\n",sh_video->i_bps);
457 sh_video->i_bps=((float)sh_video->i_bps/(float)sh_video->video.dwLength)*sh_video->fps;
458 printf("VIDEO: [%.4s] %ldx%ld %dbpp %4.2f fps %5.1f kbps (%4.1f kbyte/s)\n",
459 (char *)&sh_video->bih->biCompression,
460 sh_video->bih->biWidth,
461 sh_video->bih->biHeight,
462 sh_video->bih->biBitCount,
463 sh_video->fps,
464 sh_video->i_bps*0.008f,
465 sh_video->i_bps/1024.0f );
466
467 return demuxer;
468
469 }
470
471 //extern float initial_pts_delay;
359 472
360 void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){ 473 void demux_seek_avi(demuxer_t *demuxer,float rel_seek_secs,int flags){
474 avi_priv_t *priv=demuxer->priv;
361 demux_stream_t *d_audio=demuxer->audio; 475 demux_stream_t *d_audio=demuxer->audio;
362 demux_stream_t *d_video=demuxer->video; 476 demux_stream_t *d_video=demuxer->video;
363 sh_audio_t *sh_audio=d_audio->sh; 477 sh_audio_t *sh_audio=d_audio->sh;
364 sh_video_t *sh_video=d_video->sh; 478 sh_video_t *sh_video=d_video->sh;
365 float skip_audio_secs=0; 479 float skip_audio_secs=0;
368 //================= seek in AVI ========================== 482 //================= seek in AVI ==========================
369 int rel_seek_frames=rel_seek_secs*sh_video->fps; 483 int rel_seek_frames=rel_seek_secs*sh_video->fps;
370 int video_chunk_pos=d_video->pos; 484 int video_chunk_pos=d_video->pos;
371 int i; 485 int i;
372 486
373 skip_video_frames=0; 487 priv->skip_video_frames=0;
374 avi_audio_pts=0; 488 priv->avi_audio_pts=0;
375 489
376 // ------------ STEP 1: find nearest video keyframe chunk ------------ 490 // ------------ STEP 1: find nearest video keyframe chunk ------------
377 // find nearest video keyframe chunk pos: 491 // find nearest video keyframe chunk pos:
378 if(rel_seek_frames>0){ 492 if(rel_seek_frames>0){
379 // seek forward 493 // seek forward
380 while(video_chunk_pos<demuxer->idx_size){ 494 while(video_chunk_pos<priv->idx_size){
381 int id=((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].ckid; 495 int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
382 if(avi_stream_id(id)==d_video->id){ // video frame 496 if(avi_stream_id(id)==d_video->id){ // video frame
383 if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break; 497 if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
384 } 498 }
385 ++video_chunk_pos; 499 ++video_chunk_pos;
386 } 500 }
387 } else { 501 } else {
388 // seek backward 502 // seek backward
389 while(video_chunk_pos>=0){ 503 while(video_chunk_pos>=0){
390 int id=((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].ckid; 504 int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
391 if(avi_stream_id(id)==d_video->id){ // video frame 505 if(avi_stream_id(id)==d_video->id){ // video frame
392 if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)demuxer->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break; 506 if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
393 } 507 }
394 --video_chunk_pos; 508 --video_chunk_pos;
395 } 509 }
396 } 510 }
397 demuxer->idx_pos_a=demuxer->idx_pos_v=demuxer->idx_pos=video_chunk_pos; 511 priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=video_chunk_pos;
398 512
399 // re-calc video pts: 513 // re-calc video pts:
400 d_video->pack_no=0; 514 d_video->pack_no=0;
401 for(i=0;i<video_chunk_pos;i++){ 515 for(i=0;i<video_chunk_pos;i++){
402 int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid; 516 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
403 if(avi_stream_id(id)==d_video->id) ++d_video->pack_no; 517 if(avi_stream_id(id)==d_video->id) ++d_video->pack_no;
404 } 518 }
405 sh_video->num_frames=d_video->pack_no; 519 sh_video->num_frames=d_video->pack_no;
406 avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; 520 priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
407 d_video->pos=video_chunk_pos; 521 d_video->pos=video_chunk_pos;
408 522
409 // ------------ STEP 2: seek audio, find the right chunk & pos ------------ 523 // ------------ STEP 2: seek audio, find the right chunk & pos ------------
410 524
411 d_audio->pack_no=0; 525 d_audio->pack_no=0;
417 int last=0; 531 int last=0;
418 int len=0; 532 int len=0;
419 int skip_audio_bytes=0; 533 int skip_audio_bytes=0;
420 int curr_audio_pos=-1; 534 int curr_audio_pos=-1;
421 int audio_chunk_pos=-1; 535 int audio_chunk_pos=-1;
422 int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:demuxer->idx_size; 536 int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:priv->idx_size;
423 537
424 if(sh_audio->audio.dwSampleSize){ 538 if(sh_audio->audio.dwSampleSize){
425 // constant rate audio stream 539 // constant rate audio stream
426 #if 0 540 #if 0
427 int align; 541 int align;
428 curr_audio_pos=(avi_video_pts) * sh_audio->wf->nAvgBytesPerSec; 542 curr_audio_pos=(priv->avi_video_pts) * sh_audio->wf->nAvgBytesPerSec;
429 if(curr_audio_pos<0)curr_audio_pos=0; 543 if(curr_audio_pos<0)curr_audio_pos=0;
430 align=sh_audio->audio.dwSampleSize; 544 align=sh_audio->audio.dwSampleSize;
431 if(sh_audio->wf->nBlockAlign>align) align=sh_audio->wf->nBlockAlign; 545 if(sh_audio->wf->nBlockAlign>align) align=sh_audio->wf->nBlockAlign;
432 curr_audio_pos/=align; 546 curr_audio_pos/=align;
433 curr_audio_pos*=align; 547 curr_audio_pos*=align;
434 #else 548 #else
435 curr_audio_pos=(avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale; 549 curr_audio_pos=(priv->avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
436 curr_audio_pos*=sh_audio->audio.dwSampleSize; 550 curr_audio_pos*=sh_audio->audio.dwSampleSize;
437 #endif 551 #endif
438 552
439 // find audio chunk pos: 553 // find audio chunk pos:
440 for(i=0;i<chunk_max;i++){ 554 for(i=0;i<chunk_max;i++){
441 int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid; 555 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
442 if(avi_stream_id(id)==d_audio->id){ 556 if(avi_stream_id(id)==d_audio->id){
443 len=((AVIINDEXENTRY *)demuxer->idx)[i].dwChunkLength; 557 len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
444 audio_chunk_pos=i; ++d_audio->pack_no; 558 audio_chunk_pos=i; ++d_audio->pack_no;
445 if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){ 559 if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){
446 //if(verbose)printf("break;\n"); 560 //if(verbose)printf("break;\n");
447 break; 561 break;
448 } 562 }
451 } 565 }
452 skip_audio_bytes=curr_audio_pos-d_audio->dpos; 566 skip_audio_bytes=curr_audio_pos-d_audio->dpos;
453 567
454 } else { 568 } else {
455 // VBR audio 569 // VBR audio
456 int chunks=(avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale; 570 int chunks=(priv->avi_video_pts)*(float)sh_audio->audio.dwRate/(float)sh_audio->audio.dwScale;
457 audio_chunk_pos=0; 571 audio_chunk_pos=0;
458 572
459 // find audio chunk pos: 573 // find audio chunk pos:
460 for(i=0;i<demuxer->idx_size && chunks>0;i++){ 574 for(i=0;i<priv->idx_size && chunks>0;i++){
461 int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid; 575 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
462 if(avi_stream_id(id)==d_audio->id){ 576 if(avi_stream_id(id)==d_audio->id){
463 len=((AVIINDEXENTRY *)demuxer->idx)[i].dwChunkLength; 577 len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
464 if(i>chunk_max){ 578 if(i>chunk_max){
465 skip_audio_bytes+=len; 579 skip_audio_bytes+=len;
466 } else { 580 } else {
467 ++d_audio->pack_no; 581 ++d_audio->pack_no;
468 d_audio->dpos+=len; 582 d_audio->dpos+=len;
472 } 586 }
473 } 587 }
474 //if(audio_chunk_pos>chunk_max) audio_chunk_pos=chunk_max; 588 //if(audio_chunk_pos>chunk_max) audio_chunk_pos=chunk_max;
475 589
476 // printf("VBR seek: %5.3f -> chunk_no %d -> chunk_idx %d + skip %d \n", 590 // printf("VBR seek: %5.3f -> chunk_no %d -> chunk_idx %d + skip %d \n",
477 // avi_video_pts, audio_chunk_pos, ); 591 // priv->avi_video_pts, audio_chunk_pos, );
478 592
479 } 593 }
480 594
481 // Now we have: 595 // Now we have:
482 // audio_chunk_pos = chunk no in index table (it's <=chunk_max) 596 // audio_chunk_pos = chunk no in index table (it's <=chunk_max)
491 // d_audio->pts=initial_pts_delay+(float)apos/(float)sh_audio->wf->nAvgBytesPerSec; 605 // d_audio->pts=initial_pts_delay+(float)apos/(float)sh_audio->wf->nAvgBytesPerSec;
492 606
493 if(demuxer->type==DEMUXER_TYPE_AVI){ 607 if(demuxer->type==DEMUXER_TYPE_AVI){
494 // interleaved stream: 608 // interleaved stream:
495 if(audio_chunk_pos<video_chunk_pos){ 609 if(audio_chunk_pos<video_chunk_pos){
496 // calc skip_video_frames & adjust video pts counter: 610 // calc priv->skip_video_frames & adjust video pts counter:
497 for(i=audio_chunk_pos;i<video_chunk_pos;i++){ 611 for(i=audio_chunk_pos;i<video_chunk_pos;i++){
498 int id=((AVIINDEXENTRY *)demuxer->idx)[i].ckid; 612 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
499 if(avi_stream_id(id)==d_video->id) ++skip_video_frames; 613 if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames;
500 } 614 }
501 // requires for correct audio pts calculation (demuxer): 615 // requires for correct audio pts calculation (demuxer):
502 avi_video_pts-=skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; 616 priv->avi_video_pts-=priv->skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
503 demuxer->idx_pos_a=demuxer->idx_pos_v=demuxer->idx_pos=audio_chunk_pos; 617 priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=audio_chunk_pos;
504 } 618 }
505 } else { 619 } else {
506 // non-interleaved stream: 620 // non-interleaved stream:
507 demuxer->idx_pos_a=audio_chunk_pos; 621 priv->idx_pos_a=audio_chunk_pos;
508 demuxer->idx_pos_v=video_chunk_pos; 622 priv->idx_pos_v=video_chunk_pos;
509 demuxer->idx_pos=(audio_chunk_pos<video_chunk_pos)?audio_chunk_pos:video_chunk_pos; 623 priv->idx_pos=(audio_chunk_pos<video_chunk_pos)?audio_chunk_pos:video_chunk_pos;
510 } 624 }
511 625
512 if(verbose) printf("SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n", 626 if(verbose) printf("SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n",
513 demuxer->idx_pos,audio_chunk_pos,video_chunk_pos, 627 priv->idx_pos,audio_chunk_pos,video_chunk_pos,
514 skip_video_frames,skip_audio_bytes,skip_audio_secs); 628 priv->skip_video_frames,skip_audio_bytes,skip_audio_secs);
515 629
516 if(skip_audio_bytes){ 630 if(skip_audio_bytes){
517 demux_read_data(d_audio,NULL,skip_audio_bytes); 631 demux_read_data(d_audio,NULL,skip_audio_bytes);
518 //d_audio->pts=0; // PTS is outdated because of the raw data skipping 632 //d_audio->pts=0; // PTS is outdated because of the raw data skipping
519 } 633 }