[MPlayer-dev-eng] [PATCH] let -idx generate usable index for >4GB AVI files
Wolfram Gloger
wmglo at dent.med.uni-muenchen.de
Thu May 1 00:52:36 CEST 2003
About a year ago I added support for files >2GB to demux_avi.c. Now I
have generated a .avi file >4GB with mencoder and found that mplayer
-idx cannot create a meaningful index for it (to be expected of
course).
The patch below lets mplayer/mencoder create a usable index for .avi
files >4GB, such that seeking works in such files. Due to the use of
a private AVIextINDEXENTRY struct it also gets rid of a lot of casts
and hence makes the code a bit cleaner IMHO. I haven't yet adapted
print_index() to the new structure (any index read from the file is
printed just like before) but could of course do so.
Regards,
Wolfram.
--- libmpdemux/aviheader.h.orig Sat Nov 16 04:42:14 2002
+++ libmpdemux/aviheader.h Tue Apr 29 18:25:31 2003
@@ -84,10 +84,25 @@
#endif
+/* extended index entry, for files >4GB */
+typedef struct
+{
+ DWORD ckid;
+ DWORD dwFlags;
+ off_t ChunkOffset; // Position of chunk
+ off_t ChunkLength; // Length of chunk
+} AVIextINDEXENTRY;
+
+#define extend_AVIINDEXENTRY(h, exth) do { \
+ (exth)->ckid = (h)->ckid; \
+ (exth)->dwFlags = (h)->dwFlags; \
+ (exth)->ChunkOffset = (h)->dwChunkOffset; \
+ (exth)->ChunkLength = (h)->dwChunkLength; \
+} while (0)
typedef struct {
// index stuff:
- void* idx;
+ AVIextINDEXENTRY* idx;
int idx_size;
off_t idx_pos;
off_t idx_pos_a;
--- libmpdemux/aviheader.c.orig Fri Nov 1 18:46:43 2002
+++ libmpdemux/aviheader.c Tue Apr 29 18:30:59 2003
@@ -247,16 +247,23 @@
demuxer->movi_end=stream_tell(demuxer->stream); // fixup movi-end
if(index_mode){
int i;
+ AVIINDEXENTRY* idx_vec;
+
priv->idx_size=size2>>4;
mp_msg(MSGT_HEADER,MSGL_V,"Reading INDEX block, %d chunks for %ld frames (fpos=%p)\n",
priv->idx_size,avih.dwTotalFrames, stream_tell(demuxer->stream));
- priv->idx=malloc(priv->idx_size<<4);
-// printf("\nindex to %p !!!!! (priv=%p)\n",priv->idx,priv);
- stream_read(demuxer->stream,(char*)priv->idx,priv->idx_size<<4);
+ idx_vec=malloc(priv->idx_size<<4);
+// printf("\nindex to %p !!!!! (priv=%p)\n",idx_vec,priv);
+ stream_read(demuxer->stream,(char*)idx_vec,priv->idx_size<<4);
for (i = 0; i < priv->idx_size; i++) // swap index to machine endian
- le2me_AVIINDEXENTRY((AVIINDEXENTRY*)priv->idx + i);
+ le2me_AVIINDEXENTRY(idx_vec + i);
chunksize-=priv->idx_size<<4;
- if(verbose>=2) print_index(priv->idx,priv->idx_size);
+ if(verbose>=2) print_index(idx_vec, priv->idx_size);
+ priv->idx = malloc(priv->idx_size * sizeof(*priv->idx));
+ for (i=0; i<priv->idx_size; ++i) {
+ extend_AVIINDEXENTRY(idx_vec + i, priv->idx + i);
+ }
+ free(idx_vec);
break;
}
/* added May 2002 */
@@ -312,7 +319,7 @@
int id;
unsigned len;
off_t skip;
- AVIINDEXENTRY* idx;
+ AVIextINDEXENTRY* idx;
unsigned int c;
demuxer->filepos=stream_tell(demuxer->stream);
if(demuxer->filepos>=demuxer->movi_end && demuxer->movi_start<demuxer->movi_end) break;
@@ -328,14 +335,14 @@
if(priv->idx_pos>=priv->idx_size){
// priv->idx_size+=32;
priv->idx_size+=1024; // +16kB
- priv->idx=realloc(priv->idx,priv->idx_size*sizeof(AVIINDEXENTRY));
+ priv->idx=realloc(priv->idx,priv->idx_size*sizeof(*priv->idx));
if(!priv->idx){priv->idx_pos=0; break;} // error!
}
- idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
+ idx=&(priv->idx)[priv->idx_pos++];
idx->ckid=id;
idx->dwFlags=AVIIF_KEYFRAME; // FIXME
- idx->dwChunkOffset=(unsigned long)demuxer->filepos;
- idx->dwChunkLength=len;
+ idx->ChunkOffset=demuxer->filepos;
+ idx->ChunkLength=len;
c=stream_read_dword(demuxer->stream);
@@ -380,11 +387,9 @@
}
priv->idx_size=priv->idx_pos;
mp_msg(MSGT_HEADER,MSGL_INFO,"AVI: Generated index table for %d chunks!\n",priv->idx_size);
- if(verbose>=2) print_index(priv->idx,priv->idx_size);
+ //if(verbose>=2) print_index(priv->idx,priv->idx_size);
}
}
#undef MIN
-
-
--- libmpdemux/demux_avi.c.orig Sun Feb 2 22:32:05 2003
+++ libmpdemux/demux_avi.c Tue Apr 29 18:35:18 2003
@@ -183,7 +183,7 @@
do{
int flags=1;
- AVIINDEXENTRY *idx=NULL;
+ AVIextINDEXENTRY *idx=NULL;
#if 0
demux->filepos=stream_tell(demux->stream);
if(demux->filepos>=demux->movi_end){
@@ -197,13 +197,13 @@
//if(priv->idx_pos<0) printf("Fatal! idx_pos=%d\n",priv->idx_pos);
- idx=&((AVIINDEXENTRY *)priv->idx)[priv->idx_pos++];
+ idx=&(priv->idx)[priv->idx_pos++];
//printf("[%d]",priv->idx_pos);fflush(stdout);
- //stream_seek(demux->stream,idx.dwChunkOffset);
+ //stream_seek(demux->stream,idx.ChunkOffset);
//printf("IDX pos=%X idx.pos=%X idx.size=%X idx.flags=%X\n",demux->filepos,
- // pos-4,idx->dwChunkLength,idx->dwFlags);
+ // pos-4,idx->ChunkLength,idx->dwFlags);
if(idx->dwFlags&AVIIF_LIST){
// LIST
continue;
@@ -213,7 +213,7 @@
continue; // skip this chunk
}
- pos = priv->idx_offset + (unsigned long)idx->dwChunkOffset;
+ pos = priv->idx_offset + idx->ChunkOffset;
if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start) && (demux->stream->type!=STREAMTYPE_STREAM)){
mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! idx=0x%X \n",pos);
continue;
@@ -236,12 +236,12 @@
if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad
}
len=stream_read_dword_le(demux->stream);
-// if((len&(~1))!=(idx->dwChunkLength&(~1))){
-// if((len)!=(idx->dwChunkLength)){
- if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength);
- if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(
- len=choose_chunk_len(idx->dwChunkLength,len);
+// if((len&(~1))!=(idx->ChunkLength&(~1))){
+// if((len)!=(idx->ChunkLength)){
+ if((len!=idx->ChunkLength)&&((len+1)!=idx->ChunkLength)){
+ mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,(long)idx->ChunkLength);
+ if(len>0x200000 && idx->ChunkLength>0x200000) continue; // both values bad :(
+ len=choose_chunk_len(idx->ChunkLength,len);
}
if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;
} else {
@@ -303,7 +303,7 @@
do{
int flags=1;
- AVIINDEXENTRY *idx=NULL;
+ AVIextINDEXENTRY *idx=NULL;
int idx_pos=0;
demux->filepos=stream_tell(demux->stream);
@@ -313,7 +313,7 @@
if(priv->idx_size>0 && idx_pos<priv->idx_size){
off_t pos;
- idx=&((AVIINDEXENTRY *)priv->idx)[idx_pos];
+ idx=&(priv->idx)[idx_pos];
// idx=&priv->idx[idx_pos];
if(idx->dwFlags&AVIIF_LIST){
@@ -325,7 +325,7 @@
continue; // skip this chunk
}
- pos = priv->idx_offset+(unsigned long)idx->dwChunkOffset;
+ pos = priv->idx_offset+idx->ChunkOffset;
if((pos<demux->movi_start || pos>=demux->movi_end) && (demux->movi_end>demux->movi_start)){
mp_msg(MSGT_DEMUX,MSGL_V,"ChunkOffset out of range! current=0x%X idx=0x%X \n",demux->filepos,pos);
continue;
@@ -349,10 +349,10 @@
if(!valid_fourcc(id)) continue; // drop chunk if both id and idx bad
}
len=stream_read_dword_le(demux->stream);
- if((len!=idx->dwChunkLength)&&((len+1)!=idx->dwChunkLength)){
- mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,idx->dwChunkLength);
- if(len>0x200000 && idx->dwChunkLength>0x200000) continue; // both values bad :(
- len=choose_chunk_len(idx->dwChunkLength,len);
+ if((len!=idx->ChunkLength)&&((len+1)!=idx->ChunkLength)){
+ mp_msg(MSGT_DEMUX,MSGL_V,"ChunkSize mismatch! raw=%d idx=%ld \n",len,(long)idx->ChunkLength);
+ if(len>0x200000 && idx->ChunkLength>0x200000) continue; // both values bad :(
+ len=choose_chunk_len(idx->ChunkLength,len);
}
if(!(idx->dwFlags&AVIIF_KEYFRAME)) flags=0;
} else return 0;
@@ -467,21 +467,21 @@
if(priv->idx_size>1){
// decide index format:
#if 1
- if((unsigned long)((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset<demuxer->movi_start ||
- (unsigned long)((AVIINDEXENTRY *)priv->idx)[1].dwChunkOffset<demuxer->movi_start)
+ if((priv->idx)[0].ChunkOffset<demuxer->movi_start ||
+ (priv->idx)[1].ChunkOffset<demuxer->movi_start)
priv->idx_offset=demuxer->movi_start-4;
else
priv->idx_offset=0;
#else
- if((unsigned long)((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset<demuxer->movi_start)
+ if((priv->idx)[0].ChunkOffset<demuxer->movi_start)
priv->idx_offset=demuxer->movi_start-4;
else
priv->idx_offset=0;
#endif
mp_msg(MSGT_DEMUX,MSGL_V,"AVI index offset: 0x%X (movi=0x%X idx0=0x%X idx1=0x%X)\n",
(int)priv->idx_offset,(int)demuxer->movi_start,
- (int)((AVIINDEXENTRY *)priv->idx)[0].dwChunkOffset,
- (int)((AVIINDEXENTRY *)priv->idx)[1].dwChunkOffset);
+ (int)(priv->idx)[0].ChunkOffset,
+ (int)(priv->idx)[1].ChunkOffset);
}
// demuxer->endpos=avi_header.movi_end;
@@ -491,9 +491,9 @@
off_t a_pos=-1;
off_t v_pos=-1;
for(i=0;i<priv->idx_size;i++){
- AVIINDEXENTRY* idx=&((AVIINDEXENTRY *)priv->idx)[i];
+ AVIextINDEXENTRY* idx=&(priv->idx)[i];
demux_stream_t* ds=demux_avi_select_stream(demuxer,idx->ckid);
- off_t pos = priv->idx_offset + (unsigned long)idx->dwChunkOffset;
+ off_t pos = priv->idx_offset + idx->ChunkOffset;
if(a_pos==-1 && ds==demuxer->audio){
a_pos=pos;
if(v_pos!=-1) break;
@@ -556,8 +556,8 @@
size_t asamples=0;
int i;
for(i=0;i<priv->idx_size;i++){
- int id=avi_stream_id(((AVIINDEXENTRY *)priv->idx)[i].ckid);
- int len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
+ int id=avi_stream_id((priv->idx)[i].ckid);
+ off_t len=(priv->idx)[i].ChunkLength;
if(sh_video->ds->id == id) {
vsize+=len;
++vsamples;
@@ -622,11 +622,10 @@
sh_video_t *sh_video=d_video->sh;
float skip_audio_secs=0;
- //FIXME: OFF_T - Didn't check AVI case yet (avi files can't be >2G anyway?)
//================= seek in AVI ==========================
int rel_seek_frames=rel_seek_secs*sh_video->fps;
- int video_chunk_pos=d_video->pos;
- int i;
+ off_t video_chunk_pos=d_video->pos;
+ off_t i;
if(flags&1){
// seek absolute
@@ -645,18 +644,18 @@
if(rel_seek_frames>0){
// seek forward
while(video_chunk_pos<priv->idx_size-1){
- int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
+ int id=(priv->idx)[video_chunk_pos].ckid;
if(avi_stream_id(id)==d_video->id){ // video frame
- if((--rel_seek_frames)<0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
+ if((--rel_seek_frames)<0 && (priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
}
++video_chunk_pos;
}
} else {
// seek backward
while(video_chunk_pos>0){
- int id=((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].ckid;
+ int id=(priv->idx)[video_chunk_pos].ckid;
if(avi_stream_id(id)==d_video->id){ // video frame
- if((++rel_seek_frames)>0 && ((AVIINDEXENTRY *)priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
+ if((++rel_seek_frames)>0 && (priv->idx)[video_chunk_pos].dwFlags&AVIIF_KEYFRAME) break;
}
--video_chunk_pos;
}
@@ -666,7 +665,7 @@
// re-calc video pts:
d_video->pack_no=0;
for(i=0;i<video_chunk_pos;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
+ int id=(priv->idx)[i].ckid;
if(avi_stream_id(id)==d_video->id) ++d_video->pack_no;
}
priv->video_pack_no=
@@ -684,12 +683,12 @@
d_audio->dpos=0;
if(sh_audio){
- int i;
- int len=0;
- int skip_audio_bytes=0;
- int curr_audio_pos=-1;
- int audio_chunk_pos=-1;
- int chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:priv->idx_size;
+ off_t i;
+ off_t len=0;
+ off_t skip_audio_bytes=0;
+ off_t curr_audio_pos=-1;
+ off_t audio_chunk_pos=-1;
+ off_t chunk_max=(demuxer->type==DEMUXER_TYPE_AVI)?video_chunk_pos:priv->idx_size;
if(sh_audio->audio.dwSampleSize){
// constant rate audio stream
@@ -709,9 +708,9 @@
// find audio chunk pos:
for(i=0;i<chunk_max;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
+ int id=(priv->idx)[i].ckid;
if(avi_stream_id(id)==d_audio->id){
- len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
+ len=(priv->idx)[i].ChunkLength;
if(d_audio->dpos<=curr_audio_pos && curr_audio_pos<(d_audio->dpos+len)){
break;
}
@@ -725,7 +724,7 @@
skip_audio_bytes=curr_audio_pos-d_audio->dpos;
mp_msg(MSGT_SEEK,MSGL_V,"SEEK: i=%d (max:%d) dpos=%d (wanted:%d) \n",
- i,chunk_max,(int)d_audio->dpos,curr_audio_pos);
+ (int)i,(int)chunk_max,(int)d_audio->dpos,(int)curr_audio_pos);
} else {
// VBR audio
@@ -734,9 +733,9 @@
// find audio chunk pos:
for(i=0;i<priv->idx_size && chunks>0;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
+ int id=(priv->idx)[i].ckid;
if(avi_stream_id(id)==d_audio->id){
- len=((AVIINDEXENTRY *)priv->idx)[i].dwChunkLength;
+ len=(priv->idx)[i].ChunkLength;
if(i>chunk_max){
skip_audio_bytes+=len;
} else {
@@ -775,7 +774,7 @@
if(audio_chunk_pos<video_chunk_pos){
// calc priv->skip_video_frames & adjust video pts counter:
for(i=audio_chunk_pos;i<video_chunk_pos;i++){
- int id=((AVIINDEXENTRY *)priv->idx)[i].ckid;
+ int id=(priv->idx)[i].ckid;
if(avi_stream_id(id)==d_video->id) ++priv->skip_video_frames;
}
// requires for correct audio pts calculation (demuxer):
@@ -794,8 +793,8 @@
mp_msg(MSGT_SEEK,MSGL_V,"SEEK: idx=%d (a:%d v:%d) v.skip=%d a.skip=%d/%4.3f \n",
- (int)priv->idx_pos,audio_chunk_pos,video_chunk_pos,
- (int)priv->skip_video_frames,skip_audio_bytes,skip_audio_secs);
+ (int)priv->idx_pos,(int)audio_chunk_pos,(int)video_chunk_pos,
+ (int)priv->skip_video_frames,(int)skip_audio_bytes,skip_audio_secs);
if(skip_audio_bytes){
demux_read_data(d_audio,NULL,skip_audio_bytes);
More information about the MPlayer-dev-eng
mailing list