Mercurial > mplayer.hg
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; |