comparison libmpdemux/demux_mov.c @ 6664:b802dd0812f1

edit-list support for video - fixes various A-V sync problems (TODO: seeking)
author arpi
date Sun, 07 Jul 2002 15:21:30 +0000
parents 9eefcaf88e56
children 872235b50330
comparison
equal deleted inserted replaced
6663:5790a2576505 6664:b802dd0812f1
80 80
81 typedef struct { 81 typedef struct {
82 unsigned int num; 82 unsigned int num;
83 unsigned int dur; 83 unsigned int dur;
84 } mov_durmap_t; 84 } mov_durmap_t;
85
86 typedef struct {
87 unsigned int dur;
88 unsigned int pos;
89 int speed;
90 //
91 int frames;
92 int start_sample;
93 int start_frame;
94 int pts_offset;
95 } mov_editlist_t;
85 96
86 #define MOV_TRAK_UNKNOWN 0 97 #define MOV_TRAK_UNKNOWN 0
87 #define MOV_TRAK_VIDEO 1 98 #define MOV_TRAK_VIDEO 1
88 #define MOV_TRAK_AUDIO 2 99 #define MOV_TRAK_AUDIO 2
89 #define MOV_TRAK_FLASH 3 100 #define MOV_TRAK_FLASH 3
118 mov_chunkmap_t* chunkmap; 129 mov_chunkmap_t* chunkmap;
119 int durmap_size; 130 int durmap_size;
120 mov_durmap_t* durmap; 131 mov_durmap_t* durmap;
121 int keyframes_size; 132 int keyframes_size;
122 unsigned int* keyframes; 133 unsigned int* keyframes;
134 int editlist_size;
135 mov_editlist_t* editlist;
136 int editlist_pos;
123 // 137 //
124 void* desc; // image/sound/etc description (pointer to ImageDescription etc) 138 void* desc; // image/sound/etc description (pointer to ImageDescription etc)
125 } mov_track_t; 139 } mov_track_t;
126 140
127 void mov_build_index(mov_track_t* trak){ 141 void mov_build_index(mov_track_t* trak){
163 if (trak->chunks[i].pos == -1) 177 if (trak->chunks[i].pos == -1)
164 if (i > 0) 178 if (i > 0)
165 trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size; 179 trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size;
166 else 180 else
167 trak->chunks[i].pos = 0; /* FIXME: set initial pos */ 181 trak->chunks[i].pos = 0; /* FIXME: set initial pos */
168 }
169 #endif 182 #endif
170 183
171 // calc pts of chunks: 184 // calc pts of chunks:
172 s=0; 185 s=0;
173 for(j=0;j<trak->chunks_size;j++){ 186 for(j=0;j<trak->chunks_size;j++){
212 trak->samples[s].pts, 225 trak->samples[s].pts,
213 (int)trak->samples[s].pos, 226 (int)trak->samples[s].pos,
214 trak->samples[s].size); 227 trak->samples[s].size);
215 pos+=trak->samples[s].size; 228 pos+=trak->samples[s].size;
216 ++s; 229 ++s;
230 }
231 }
232
233 // precalc editlist entries
234 if(trak->editlist_size>0){
235 int frame=0;
236 int e_pts=0;
237 for(i=0;i<trak->editlist_size;i++){
238 mov_editlist_t* el=&trak->editlist[i];
239 int sample=0;
240 int pts=el->pos;
241 el->start_frame=frame;
242 if(pts<0){
243 // skip!
244 el->frames=0; continue;
245 }
246 // find start sample
247 for(;sample<trak->samples_size;sample++){
248 if(pts<=trak->samples[sample].pts) break;
249 }
250 el->start_sample=sample;
251 el->pts_offset=e_pts-trak->samples[sample].pts;
252 pts+=el->dur;
253 e_pts+=el->dur;
254 // find end sample
255 for(;sample<trak->samples_size;sample++){
256 if(pts<=trak->samples[sample].pts) break;
257 }
258 el->frames=sample-el->start_sample;
259 frame+=el->frames;
217 } 260 }
218 } 261 }
219 262
220 } 263 }
221 264
584 int i; 627 int i;
585 628
586 mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sEdit list table (%d entries) (ver:%d,flags:%ld)\n", 629 mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*sEdit list table (%d entries) (ver:%d,flags:%ld)\n",
587 level, "",entries, ver, flags); 630 level, "",entries, ver, flags);
588 #if 1 631 #if 1
632 trak->editlist_size=entries;
633 trak->editlist=malloc(trak->editlist_size*sizeof(mov_editlist_t));
589 for (i=0;i<entries;i++) 634 for (i=0;i<entries;i++)
590 { 635 {
591 int dur=stream_read_dword(demuxer->stream); 636 int dur=stream_read_dword(demuxer->stream);
592 int mt=stream_read_dword(demuxer->stream); 637 int mt=stream_read_dword(demuxer->stream);
593 int mr=stream_read_dword(demuxer->stream); // 16.16fp 638 int mr=stream_read_dword(demuxer->stream); // 16.16fp
639 trak->editlist[i].dur=dur;
640 trak->editlist[i].pos=mt;
641 trak->editlist[i].speed=mr;
594 mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n",level,"", 642 mp_msg(MSGT_DEMUX, MSGL_V,"MOV: %*s entry#%d: duration: %d start time: %d speed: %3.1fx\n",level,"",
595 i, 643 i,
596 dur,mt,(float)mr/65536.0f); 644 dur,mt,(float)mr/65536.0f);
597 } 645 }
598 #endif 646 #endif
1320 } 1368 }
1321 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts); 1369 mp_msg(MSGT_DEMUX, MSGL_DBG2, "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts);
1322 } /* MOV_TRAK_AUDIO */ 1370 } /* MOV_TRAK_AUDIO */
1323 pos=trak->chunks[trak->pos].pos; 1371 pos=trak->chunks[trak->pos].pos;
1324 } else { 1372 } else {
1373 int frame=trak->pos;
1374 // editlist support:
1375 if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){
1376 int t;
1377 // find the right editlist entry:
1378 if(frame<trak->editlist[trak->editlist_pos].start_frame)
1379 trak->editlist_pos=0;
1380 while(trak->editlist_pos<trak->editlist_size-1 &&
1381 frame>=trak->editlist[trak->editlist_pos+1].start_frame)
1382 ++trak->editlist_pos;
1383 if(frame>=trak->editlist[trak->editlist_pos].start_frame+
1384 trak->editlist[trak->editlist_pos].frames) return 0; // EOF
1385 // calc real frame index:
1386 frame-=trak->editlist[trak->editlist_pos].start_frame;
1387 frame+=trak->editlist[trak->editlist_pos].start_sample;
1388 // calc pts:
1389 pts=(float)(trak->samples[frame].pts+
1390 trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale;
1391 } else {
1392 if(frame>=trak->samples_size) return 0; // EOF
1393 pts=(float)trak->samples[frame].pts/(float)trak->timescale;
1394 }
1325 // read sample: 1395 // read sample:
1326 if(trak->pos>=trak->samples_size) return 0; // EOF 1396 stream_seek(demuxer->stream,trak->samples[frame].pos);
1327 stream_seek(demuxer->stream,trak->samples[trak->pos].pos); 1397 x=trak->samples[frame].size;
1328 pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale; 1398 pos=trak->samples[frame].pos;
1329 x=trak->samples[trak->pos].size;
1330 pos=trak->samples[trak->pos].pos;
1331 } 1399 }
1332 if(trak->pos==0 && trak->stream_header_len>0){ 1400 if(trak->pos==0 && trak->stream_header_len>0){
1333 // we have to append the stream header... 1401 // we have to append the stream header...
1334 demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len); 1402 demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len);
1335 memcpy(dp->buffer,trak->stream_header,trak->stream_header_len); 1403 memcpy(dp->buffer,trak->stream_header,trak->stream_header_len);