comparison libmpdemux/demux_avi.c @ 8030:2b39ff3860b7

cleanup of .AVI timestamp calculation (ugly hack from mplayer.c removed, instead doing it in demux_avi.c, storing private data in priv insteda of demuxer structs)
author arpi
date Sat, 02 Nov 2002 00:45:12 +0000
parents ffe8bfaa2851
children e64ff1e1593c
comparison
equal deleted inserted replaced
8029:6ccd72982b88 8030:2b39ff3860b7
12 #include "demuxer.h" 12 #include "demuxer.h"
13 #include "stheader.h" 13 #include "stheader.h"
14 14
15 #include "aviheader.h" 15 #include "aviheader.h"
16 16
17 // PTS: 0=interleaved 1=BPS-based
18 int pts_from_bps=1;
19
17 // Select ds from ID 20 // Select ds from ID
18 demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){ 21 demux_stream_t* demux_avi_select_stream(demuxer_t *demux,unsigned int id){
19 int stream_id=avi_stream_id(id); 22 int stream_id=avi_stream_id(id);
20 23
21 // printf("demux_avi_select_stream(%d) {a:%d/v:%d}\n",stream_id, 24 // printf("demux_avi_select_stream(%d) {a:%d/v:%d}\n",stream_id,
30 demux->audio->id=stream_id; 33 demux->audio->id=stream_id;
31 34
32 if(stream_id==demux->audio->id){ 35 if(stream_id==demux->audio->id){
33 if(!demux->audio->sh){ 36 if(!demux->audio->sh){
34 sh_audio_t* sh; 37 sh_audio_t* sh;
38 avi_priv_t *priv=demux->priv;
35 sh=demux->audio->sh=demux->a_streams[stream_id]; 39 sh=demux->audio->sh=demux->a_streams[stream_id];
36 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI audio ID = %d\n",demux->audio->id); 40 mp_msg(MSGT_DEMUX,MSGL_V,"Auto-selected AVI audio ID = %d\n",demux->audio->id);
37 if(sh->wf){ 41 if(sh->wf){
38 demux->audio->block_size=sh->wf->nBlockAlign; 42 priv->audio_block_size=sh->wf->nBlockAlign;
39 if(!demux->audio->block_size){ 43 if(!priv->audio_block_size){
40 // for PCM audio we can calculate the blocksize: 44 // for PCM audio we can calculate the blocksize:
41 if(sh->format==1) demux->audio->block_size=sh->wf->nChannels*(sh->wf->wBitsPerSample/8); 45 if(sh->format==1)
42 if(!demux->audio->block_size) demux->audio->block_size=1; // bug! 46 priv->audio_block_size=sh->wf->nChannels*(sh->wf->wBitsPerSample/8);
47 else
48 priv->audio_block_size=1; // hope the best...
43 } 49 }
50 } else {
51 priv->audio_block_size=sh->audio.dwSampleSize;
44 } 52 }
45 //printf("&&&&& setting blocksize to %d &&&&&\n",demux->audio->block_size); 53 //printf("&&&&& setting blocksize to %d &&&&&\n",demux->audio->block_size);
46 } 54 }
47 return demux->audio; 55 return demux->audio;
48 } 56 }
86 94
87 static int demux_avi_read_packet(demuxer_t *demux,demux_stream_t *ds,unsigned int id,unsigned int len,int idxpos,int flags){ 95 static int demux_avi_read_packet(demuxer_t *demux,demux_stream_t *ds,unsigned int id,unsigned int len,int idxpos,int flags){
88 avi_priv_t *priv=demux->priv; 96 avi_priv_t *priv=demux->priv;
89 int skip; 97 int skip;
90 float pts=0; 98 float pts=0;
91 // demux_stream_t *ds=demux_avi_select_stream(demux,id);
92 99
93 mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_avi.read_packet: %X\n",id); 100 mp_dbg(MSGT_DEMUX,MSGL_DBG3,"demux_avi.read_packet: %X\n",id);
94 101
95 if(ds==demux->audio){ 102 if(ds==demux->audio){
96
97 if(priv->pts_corrected==0){ 103 if(priv->pts_corrected==0){
98 // printf("\rYYY-A A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts); 104 // printf("\rYYY-A A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts);
99 if(priv->pts_has_video){ 105 if(priv->pts_has_video){
100 // we have video pts now 106 // we have video pts now
101 float delay=0; 107 float delay=0;
105 //priv->pts_correction=-priv->avi_audio_pts+delay; 111 //priv->pts_correction=-priv->avi_audio_pts+delay;
106 priv->pts_correction=delay-priv->avi_audio_pts; 112 priv->pts_correction=delay-priv->avi_audio_pts;
107 priv->avi_audio_pts+=priv->pts_correction; 113 priv->avi_audio_pts+=priv->pts_correction;
108 priv->pts_corrected=1; 114 priv->pts_corrected=1;
109 } else 115 } else
110 priv->pts_corr_bytes+=len; 116 priv->pts_corr_bytes+=len;
111 } 117 }
112 pts=priv->avi_audio_pts; //+priv->pts_correction; 118 if(pts_from_bps){
113 priv->avi_audio_pts=0; 119 pts = priv->audio_block_no *
120 (float)((sh_audio_t*)demux->audio->sh)->audio.dwScale /
121 (float)((sh_audio_t*)demux->audio->sh)->audio.dwRate;
122 } else
123 pts=priv->avi_audio_pts; //+priv->pts_correction;
124 priv->avi_audio_pts=0;
125 // update blockcount:
126 priv->audio_block_no+=priv->audio_block_size ?
127 ((len+priv->audio_block_size-1)/priv->audio_block_size) : 1;
114 } else 128 } else
115 if(ds==demux->video){ 129 if(ds==demux->video){
116 // video 130 // video
117 if(priv->skip_video_frames>0){ 131 if(priv->skip_video_frames>0){
118 // drop frame (seeking) 132 // drop frame (seeking)
119 --priv->skip_video_frames; 133 --priv->skip_video_frames;
120 ds=NULL; 134 ds=NULL;
121 // } else {
122 // pts=priv->avi_video_pts;
123 } 135 }
124 // ezt a 2 sort lehet hogy fell kell majd cserelni: 136
125 //priv->avi_video_pts+=avi_pts_frametime; 137 pts = priv->avi_video_pts = priv->video_pack_no *
126 //priv->avi_video_pts+=(float)avi_header.video.dwScale/(float)avi_header.video.dwRate;
127 //priv->avi_video_pts+=((sh_video_t*)ds->sh)->frametime;
128 // FIXME!!!
129 #if 1
130 // printf("ds=0x%X\n",ds);
131 // printf("packno=%d\n",ds->pack_no);
132 // printf("### pack_no=%d\n",demux->video->pack_no+demux->video->packs);
133 priv->avi_video_pts = (demux->video->pack_no+demux->video->packs) *
134 (float)((sh_video_t*)demux->video->sh)->video.dwScale / 138 (float)((sh_video_t*)demux->video->sh)->video.dwScale /
135 (float)((sh_video_t*)demux->video->sh)->video.dwRate; 139 (float)((sh_video_t*)demux->video->sh)->video.dwRate;
136 #else
137 priv->avi_video_pts+=(float)((sh_video_t*)(demux->video->sh))->video.dwScale/(float)((sh_video_t*)(demux->video->sh))->video.dwRate;
138 // priv->avi_video_pts+=avi_video_ftime;
139 #endif
140 // printf("\rYYY-V A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts); 140 // printf("\rYYY-V A: %5.3f V: %5.3f \n",priv->avi_audio_pts,priv->avi_video_pts);
141
141 priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction; 142 priv->avi_audio_pts=priv->avi_video_pts+priv->pts_correction;
142 priv->pts_has_video=1; 143 priv->pts_has_video=1;
143 144
144 pts=priv->avi_video_pts; 145 if(ds) ++priv->video_pack_no;
145 146
146 //printf("read pack_no: %d pts %5.3f \n",demux->video->pack_no+demux->video->packs,pts); 147 //printf("read pack_no: %d pts %5.3f \n",demux->video->pack_no+demux->video->packs,pts);
147 148 }
148 } 149
149
150 // len=stream_read_dword_le(demux->stream);
151 skip=(len+1)&(~1); // total bytes in this chunk 150 skip=(len+1)&(~1); // total bytes in this chunk
152 151
153 if(ds){ 152 if(ds){
154 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id); 153 mp_dbg(MSGT_DEMUX,MSGL_DBG2,"DEMUX_AVI: Read %d data bytes from packet %04X\n",len,id);
155 ds_read_packet(ds,demux->stream,len,pts,idxpos,flags); 154 ds_read_packet(ds,demux->stream,len,pts,idxpos,flags);
339 id=idx->ckid; // use index if valid 338 id=idx->ckid; // use index if valid
340 else 339 else
341 if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad 340 if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad
342 } 341 }
343 len=stream_read_dword_le(demux->stream); 342 len=stream_read_dword_le(demux->stream);
344 // if((len&(~1))!=(idx->dwChunkLength&(~1))){
345 // if((len)!=(idx->dwChunkLength)){
346 if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){ 343 if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){
347 mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength); 344 mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength);
348 if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :( 345 if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(
349 len=choose_chunk_len(idx->dwChunkLength,len); 346 len=choose_chunk_len(idx->dwChunkLength,len);
350 } 347 }
415 } while(ret!=1); 412 } while(ret!=1);
416 fpos[0]=stream_tell(demux->stream); 413 fpos[0]=stream_tell(demux->stream);
417 return 1; 414 return 1;
418 } 415 }
419 416
420 //extern int audio_id;
421 //extern int video_id;
422 //extern int index_mode; // -1=untouched 0=don't use index 1=use (geneate) index
423 //extern int force_ni;
424 //extern int pts_from_bps;
425
426 // AVI demuxer parameters: 417 // AVI demuxer parameters:
427 int index_mode=-1; // -1=untouched 0=don't use index 1=use (geneate) index 418 int index_mode=-1; // -1=untouched 0=don't use index 1=use (geneate) index
428 int force_ni=0; // force non-interleaved AVI parsing 419 int force_ni=0; // force non-interleaved AVI parsing
429
430 // PTS: 0=interleaved 1=BPS-based
431 #ifdef AVI_SYNC_BPS
432 int pts_from_bps=1;
433 #else
434 int pts_from_bps=0;
435 #endif
436 420
437 void read_avi_header(demuxer_t *demuxer,int index_mode); 421 void read_avi_header(demuxer_t *demuxer,int index_mode);
438 422
439 demuxer_t* demux_open_avi(demuxer_t* demuxer){ 423 demuxer_t* demux_open_avi(demuxer_t* demuxer){
440 demux_stream_t *d_audio=demuxer->audio; 424 demux_stream_t *d_audio=demuxer->audio;
447 priv->avi_audio_pts=priv->avi_video_pts=0.0f; 431 priv->avi_audio_pts=priv->avi_video_pts=0.0f;
448 priv->pts_correction=0.0f; 432 priv->pts_correction=0.0f;
449 priv->skip_video_frames=0; 433 priv->skip_video_frames=0;
450 priv->pts_corr_bytes=0; 434 priv->pts_corr_bytes=0;
451 priv->pts_has_video=priv->pts_corrected=0; 435 priv->pts_has_video=priv->pts_corrected=0;
436 priv->video_pack_no=0;
437 priv->audio_block_no=0;
438 priv->audio_block_size=0;
452 demuxer->priv=(void*)priv; 439 demuxer->priv=(void*)priv;
453 440
454 //---- AVI header: 441 //---- AVI header:
455 read_avi_header(demuxer,(demuxer->stream->type!=STREAMTYPE_STREAM)?index_mode:-2); 442 read_avi_header(demuxer,(demuxer->stream->type!=STREAMTYPE_STREAM)?index_mode:-2);
456 443
634 d_video->pack_no=0; 621 d_video->pack_no=0;
635 for(i=0;i<video_chunk_pos;i++){ 622 for(i=0;i<video_chunk_pos;i++){
636 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid; 623 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
637 if(avi_stream_id(id)==d_video->id) ++d_video->pack_no; 624 if(avi_stream_id(id)==d_video->id) ++d_video->pack_no;
638 } 625 }
626 priv->video_pack_no=
639 sh_video->num_frames=sh_video->num_frames_decoded=d_video->pack_no; 627 sh_video->num_frames=sh_video->num_frames_decoded=d_video->pack_no;
640 priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; 628 priv->avi_video_pts=d_video->pack_no*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
641 d_video->pos=video_chunk_pos; 629 d_video->pos=video_chunk_pos;
642 630
643 mp_msg(MSGT_SEEK,MSGL_DBG2,"V_SEEK: pack=%d pts=%5.3f chunk=%d \n",d_video->pack_no,priv->avi_video_pts,video_chunk_pos); 631 mp_msg(MSGT_SEEK,MSGL_DBG2,"V_SEEK: pack=%d pts=%5.3f chunk=%d \n",d_video->pack_no,priv->avi_video_pts,video_chunk_pos);
644 632
645 // ------------ STEP 2: seek audio, find the right chunk & pos ------------ 633 // ------------ STEP 2: seek audio, find the right chunk & pos ------------
646 634
647 d_audio->pack_no=0; 635 d_audio->pack_no=0;
648 d_audio->block_no=0; 636 // d_audio->block_no=0;
637 priv->audio_block_no=0;
649 d_audio->dpos=0; 638 d_audio->dpos=0;
650 639
651 if(sh_audio){ 640 if(sh_audio){
652 int i; 641 int i;
653 int len=0; 642 int len=0;
675 // find audio chunk pos: 664 // find audio chunk pos:
676 for(i=0;i<chunk_max;i++){ 665 for(i=0;i<chunk_max;i++){
677 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid; 666 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
678 if(avi_stream_id(id)==d_audio->id){ 667 if(avi_stream_id(id)==d_audio->id){
679 len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength; 668 len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
680 ++d_audio->pack_no;
681 d_audio->block_no+=(len+d_audio->block_size-1)/d_audio->block_size;
682 if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){ 669 if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){
683 break; 670 break;
684 } 671 }
672 ++d_audio->pack_no;
673 priv->audio_block_no+=priv->audio_block_size ?
674 ((len+priv->audio_block_size-1)/priv->audio_block_size) : 1;
685 d_audio->dpos+=len; 675 d_audio->dpos+=len;
686 } 676 }
687 } 677 }
688 audio_chunk_pos=i; 678 audio_chunk_pos=i;
689 skip_audio_bytes=curr_audio_pos-d_audio->dpos; 679 skip_audio_bytes=curr_audio_pos-d_audio->dpos;
703 len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength; 693 len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
704 if(i>chunk_max){ 694 if(i>chunk_max){
705 skip_audio_bytes+=len; 695 skip_audio_bytes+=len;
706 } else { 696 } else {
707 ++d_audio->pack_no; 697 ++d_audio->pack_no;
708 d_audio->block_no+=(len+d_audio->block_size-1)/d_audio->block_size; 698 priv->audio_block_no+=priv->audio_block_size ?
699 ((len+priv->audio_block_size-1)/priv->audio_block_size) : 1;
709 d_audio->dpos+=len; 700 d_audio->dpos+=len;
710 audio_chunk_pos=i; 701 audio_chunk_pos=i;
711 } 702 }
712 // --chunks; 703 // --chunks;
713 chunks-=(len+d_audio->block_size-1)/d_audio->block_size; 704 if(priv->audio_block_size)
705 chunks-=(len+priv->audio_block_size-1)/priv->audio_block_size;
714 } 706 }
715 } 707 }
716 //if(audio_chunk_pos>chunk_max) audio_chunk_pos=chunk_max; 708 //if(audio_chunk_pos>chunk_max) audio_chunk_pos=chunk_max;
717 709
718 // printf("VBR seek: %5.3f -> chunk_no %d -> chunk_idx %d + skip %d \n", 710 // printf("VBR seek: %5.3f -> chunk_no %d -> chunk_idx %d + skip %d \n",
740 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid; 732 int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
741 if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames; 733 if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames;
742 } 734 }
743 // requires for correct audio pts calculation (demuxer): 735 // requires for correct audio pts calculation (demuxer):
744 priv->avi_video_pts-=priv->skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate; 736 priv->avi_video_pts-=priv->skip_video_frames*(float)sh_video->video.dwScale/(float)sh_video->video.dwRate;
737 priv->avi_audio_pts=priv->avi_video_pts;
738 // set index position:
745 priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=audio_chunk_pos; 739 priv->idx_pos_a=priv->idx_pos_v=priv->idx_pos=audio_chunk_pos;
746 } 740 }
747 } else { 741 } else {
748 // non-interleaved stream: 742 // non-interleaved stream:
749 priv->idx_pos_a=audio_chunk_pos; 743 priv->idx_pos_a=audio_chunk_pos;