# HG changeset patch # User arpi # Date 1026055290 0 # Node ID b802dd0812f1148946f1a4dbb74d8dad5c96a266 # Parent 5790a25765057ecd0c27cf445c736c7a154e59d2 edit-list support for video - fixes various A-V sync problems (TODO: seeking) diff -r 5790a2576505 -r b802dd0812f1 libmpdemux/demux_mov.c --- a/libmpdemux/demux_mov.c Sun Jul 07 04:07:57 2002 +0000 +++ b/libmpdemux/demux_mov.c Sun Jul 07 15:21:30 2002 +0000 @@ -83,6 +83,17 @@ unsigned int dur; } mov_durmap_t; +typedef struct { + unsigned int dur; + unsigned int pos; + int speed; + // + int frames; + int start_sample; + int start_frame; + int pts_offset; +} mov_editlist_t; + #define MOV_TRAK_UNKNOWN 0 #define MOV_TRAK_VIDEO 1 #define MOV_TRAK_AUDIO 2 @@ -120,6 +131,9 @@ mov_durmap_t* durmap; int keyframes_size; unsigned int* keyframes; + int editlist_size; + mov_editlist_t* editlist; + int editlist_pos; // void* desc; // image/sound/etc description (pointer to ImageDescription etc) } mov_track_t; @@ -165,7 +179,6 @@ trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size; else trak->chunks[i].pos = 0; /* FIXME: set initial pos */ - } #endif // calc pts of chunks: @@ -217,6 +230,36 @@ } } + // precalc editlist entries + if(trak->editlist_size>0){ + int frame=0; + int e_pts=0; + for(i=0;ieditlist_size;i++){ + mov_editlist_t* el=&trak->editlist[i]; + int sample=0; + int pts=el->pos; + el->start_frame=frame; + if(pts<0){ + // skip! + el->frames=0; continue; + } + // find start sample + for(;samplesamples_size;sample++){ + if(pts<=trak->samples[sample].pts) break; + } + el->start_sample=sample; + el->pts_offset=e_pts-trak->samples[sample].pts; + pts+=el->dur; + e_pts+=el->dur; + // find end sample + for(;samplesamples_size;sample++){ + if(pts<=trak->samples[sample].pts) break; + } + el->frames=sample-el->start_sample; + frame+=el->frames; + } + } + } #define MOV_MAX_TRACKS 256 @@ -586,11 +629,16 @@ mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sEdit list table (%d entries) (ver:%d,flags:%ld)\n", level, "",entries, ver, flags); #if 1 + trak->editlist_size=entries; + trak->editlist=malloc(trak->editlist_size*sizeof(mov_editlist_t)); for (i=0;istream); int mt=stream_read_dword(demuxer->stream); int mr=stream_read_dword(demuxer->stream); // 16.16fp + trak->editlist[i].dur=dur; + trak->editlist[i].pos=mt; + trak->editlist[i].speed=mr; mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n",level,"", i, dur,mt,(float)mr/65536.0f); @@ -1322,12 +1370,32 @@ } /* MOV_TRAK_AUDIO */ pos=trak->chunks[trak->pos].pos; } else { + int frame=trak->pos; + // editlist support: + if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){ + int t; + // find the right editlist entry: + if(frameeditlist[trak->editlist_pos].start_frame) + trak->editlist_pos=0; + while(trak->editlist_poseditlist_size-1 && + frame>=trak->editlist[trak->editlist_pos+1].start_frame) + ++trak->editlist_pos; + if(frame>=trak->editlist[trak->editlist_pos].start_frame+ + trak->editlist[trak->editlist_pos].frames) return 0; // EOF + // calc real frame index: + frame-=trak->editlist[trak->editlist_pos].start_frame; + frame+=trak->editlist[trak->editlist_pos].start_sample; + // calc pts: + pts=(float)(trak->samples[frame].pts+ + trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale; + } else { + if(frame>=trak->samples_size) return 0; // EOF + pts=(float)trak->samples[frame].pts/(float)trak->timescale; + } // read sample: - if(trak->pos>=trak->samples_size) return 0; // EOF - stream_seek(demuxer->stream,trak->samples[trak->pos].pos); - pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; - x=trak->samples[trak->pos].size; - pos=trak->samples[trak->pos].pos; + stream_seek(demuxer->stream,trak->samples[frame].pos); + x=trak->samples[frame].size; + pos=trak->samples[frame].pos; } if(trak->pos==0 && trak->stream_header_len>0){ // we have to append the stream header...