comparison libmpdemux/demux_real.c @ 11596:6d377637ea60

Proper runtime index generation with support for growing files. Patch by rgselk <rgselknospam@yahoo.com>
author alex
date Mon, 08 Dec 2003 22:03:49 +0000
parents fef5c880a61c
children a7c9ad2e4c45
comparison
equal deleted inserted replaced
11595:95413c6d76a0 11596:6d377637ea60
39 #define MAX_STREAMS 32 39 #define MAX_STREAMS 32
40 40
41 typedef struct { 41 typedef struct {
42 int timestamp; 42 int timestamp;
43 int offset; 43 int offset;
44 int packetno; 44 // int packetno;
45 int len; /* only filled by our index generator */ 45 // int len; /* only filled by our index generator */
46 int flags; /* only filled by our index generator */ 46 // int flags; /* only filled by our index generator */
47 } real_index_table_t; 47 } real_index_table_t;
48 48
49 typedef struct { 49 typedef struct {
50 /* for seeking */ 50 /* for seeking */
51 int index_chunk_offset; 51 int index_chunk_offset;
52 real_index_table_t *index_table[MAX_STREAMS]; 52 real_index_table_t *index_table[MAX_STREAMS];
53 53
54 // int *index_table[MAX_STREAMS]; 54 // int *index_table[MAX_STREAMS];
55 int index_table_size[MAX_STREAMS]; 55 int index_table_size[MAX_STREAMS];
56 int index_malloc_size[MAX_STREAMS];
56 int data_chunk_offset; 57 int data_chunk_offset;
57 int num_of_packets; 58 int num_of_packets;
58 int current_packet; 59 int current_packet;
59 60
60 // need for seek 61 // need for seek
125 entries = priv->index_table_size[stream_id]; 126 entries = priv->index_table_size[stream_id];
126 127
127 printf("Index table for stream %d\n", stream_id); 128 printf("Index table for stream %d\n", stream_id);
128 for (i = 0; i < entries; i++) 129 for (i = 0; i < entries; i++)
129 { 130 {
131 #if 1
132 printf("i: %d, pos: %d, timestamp: %d\n", i, index[i].offset, index[i].timestamp);
133 #else
130 printf("packetno: %x pos: %x len: %x timestamp: %x flags: %x\n", 134 printf("packetno: %x pos: %x len: %x timestamp: %x flags: %x\n",
131 index[i].packetno, index[i].offset, index[i].len, index[i].timestamp, 135 index[i].packetno, index[i].offset, index[i].len, index[i].timestamp,
132 index[i].flags); 136 index[i].flags);
137 #endif
133 } 138 }
134 } 139 }
135 140
136 static int parse_index_chunk(demuxer_t *demuxer) 141 static int parse_index_chunk(demuxer_t *demuxer)
137 { 142 {
188 for (i = 0; i < entries; i++) 193 for (i = 0; i < entries; i++)
189 { 194 {
190 stream_skip(demuxer->stream, 2); /* version */ 195 stream_skip(demuxer->stream, 2); /* version */
191 priv->index_table[stream_id][i].timestamp = stream_read_dword(demuxer->stream); 196 priv->index_table[stream_id][i].timestamp = stream_read_dword(demuxer->stream);
192 priv->index_table[stream_id][i].offset = stream_read_dword(demuxer->stream); 197 priv->index_table[stream_id][i].offset = stream_read_dword(demuxer->stream);
193 priv->index_table[stream_id][i].packetno = stream_read_dword(demuxer->stream); 198 stream_skip(demuxer->stream, 4); /* packetno */
199 // priv->index_table[stream_id][i].packetno = stream_read_dword(demuxer->stream);
194 // printf("Index table: Stream#%d: entry: %d: pos: %d\n", 200 // printf("Index table: Stream#%d: entry: %d: pos: %d\n",
195 // stream_id, i, priv->index_table[stream_id][i].offset); 201 // stream_id, i, priv->index_table[stream_id][i].offset);
196 } 202 }
197 203
198 dump_index(demuxer, stream_id); 204 dump_index(demuxer, stream_id);
209 return 0; 215 return 0;
210 else 216 else
211 return 1; 217 return 1;
212 } 218 }
213 219
220 #if 1
221
222 static void add_index_item(demuxer_t *demuxer, int stream_id, int timestamp, int offset)
223 {
224 if (index_mode > 0 && (unsigned)stream_id < MAX_STREAMS)
225 {
226 real_priv_t *priv = demuxer->priv;
227 real_index_table_t *index;
228 if (priv->index_table_size[stream_id] >= priv->index_malloc_size[stream_id])
229 {
230 if (priv->index_malloc_size[stream_id] == 0)
231 priv->index_malloc_size[stream_id] = 2048;
232 else
233 priv->index_malloc_size[stream_id] += priv->index_malloc_size[stream_id] / 2;
234 priv->index_table[stream_id] = realloc(priv->index_table[stream_id], priv->index_malloc_size[stream_id]*sizeof(priv->index_table[0][0]));
235 }
236 if (priv->index_table_size[stream_id] > 0)
237 {
238 index = &priv->index_table[stream_id][priv->index_table_size[stream_id] - 1];
239 if (index->timestamp >= timestamp || index->offset >= offset)
240 return;
241 }
242 index = &priv->index_table[stream_id][priv->index_table_size[stream_id]++];
243 index->timestamp = timestamp;
244 index->offset = offset;
245 demuxer->seekable = 1;
246 }
247 }
248
249 static void add_index_segment(demuxer_t *demuxer, int seek_stream_id, int seek_timestamp)
250 {
251 int tag, len, stream_id, timestamp, flags;
252 if (seek_timestamp != -1 && (unsigned)seek_stream_id >= MAX_STREAMS)
253 return;
254 while (1)
255 {
256 demuxer->filepos = stream_tell(demuxer->stream);
257
258 tag = stream_read_dword(demuxer->stream);
259 if (tag == MKTAG('A', 'T', 'A', 'D'))
260 {
261 stream_skip(demuxer->stream, 14);
262 continue; /* skip to next loop */
263 }
264 len = tag & 0xffff;
265 if (tag == -256 || len < 12)
266 break;
267
268 stream_id = stream_read_word(demuxer->stream);
269 timestamp = stream_read_dword(demuxer->stream);
270
271 stream_skip(demuxer->stream, 1); /* reserved */
272 flags = stream_read_char(demuxer->stream);
273
274 if (flags == -256)
275 break;
276
277 if (flags & 2)
278 {
279 add_index_item(demuxer, stream_id, timestamp, demuxer->filepos);
280 if (stream_id == seek_stream_id && timestamp >= seek_timestamp)
281 {
282 stream_seek(demuxer->stream, demuxer->filepos);
283 return;
284 }
285 }
286 // printf("Index: stream=%d packet=%d timestamp=%d len=%d flags=0x%x datapos=0x%x\n", stream_id, entries, timestamp, len, flags, index->offset);
287 /* skip data */
288 stream_skip(demuxer->stream, len-12);
289 }
290 }
291
292 static int generate_index(demuxer_t *demuxer)
293 {
294 real_priv_t *priv = demuxer->priv;
295 int origpos = stream_tell(demuxer->stream);
296 int data_pos = priv->data_chunk_offset-10;
297 int i;
298 int tag;
299
300 stream_seek(demuxer->stream, data_pos);
301 tag = stream_read_dword(demuxer->stream);
302 if (tag != MKTAG('A', 'T', 'A', 'D'))
303 {
304 printf("Something went wrong, no data chunk found on given address (%d)\n", data_pos);
305 }
306 else
307 {
308 stream_skip(demuxer->stream, 14);
309 add_index_segment(demuxer, -1, -1);
310 }
311 demuxer->seekable = 0;
312 for (i = 0; i < MAX_STREAMS; i++)
313 {
314 if (priv->index_table_size[i] > 0)
315 {
316 dump_index(demuxer, i);
317 demuxer->seekable = 1; /* got index, we're able to seek */
318 }
319 }
320 stream_reset(demuxer->stream);
321 stream_seek(demuxer->stream, origpos);
322 return 0;
323 }
324
325 #else
326
214 static int generate_index(demuxer_t *demuxer) 327 static int generate_index(demuxer_t *demuxer)
215 { 328 {
216 real_priv_t *priv = demuxer->priv; 329 real_priv_t *priv = demuxer->priv;
217 int origpos = stream_tell(demuxer->stream); 330 int origpos = stream_tell(demuxer->stream);
218 int data_pos = priv->data_chunk_offset-10; 331 int data_pos = priv->data_chunk_offset-10;
300 if (i == -256) 413 if (i == -256)
301 return 0; 414 return 0;
302 else 415 else
303 return 1; 416 return 1;
304 } 417 }
418 #endif
419
305 420
306 int real_check_file(demuxer_t* demuxer) 421 int real_check_file(demuxer_t* demuxer)
307 { 422 {
308 real_priv_t *priv; 423 real_priv_t *priv;
309 int c; 424 int c;
431 reserved = stream_read_char(demuxer->stream); 546 reserved = stream_read_char(demuxer->stream);
432 flags = stream_read_char(demuxer->stream); 547 flags = stream_read_char(demuxer->stream);
433 /* flags: */ 548 /* flags: */
434 /* 0x1 - reliable */ 549 /* 0x1 - reliable */
435 /* 0x2 - keyframe */ 550 /* 0x2 - keyframe */
551
552 if (flags & 2)
553 add_index_item(demuxer, stream_id, timestamp, demuxer->filepos);
436 554
437 // printf("%08X: packet v%d len=%4d id=%d pts=%6d rvd=%d flags=%d \n", 555 // printf("%08X: packet v%d len=%4d id=%d pts=%6d rvd=%d flags=%d \n",
438 // (int)demuxer->filepos,(int)version,(int)len, stream_id, 556 // (int)demuxer->filepos,(int)version,(int)len, stream_id,
439 // (int) timestamp, reserved, flags); 557 // (int) timestamp, reserved, flags);
440 558
505 dp->pos = demuxer->filepos; 623 dp->pos = demuxer->filepos;
506 dp->flags = (flags & 0x2) ? 0x10 : 0; 624 dp->flags = (flags & 0x2) ? 0x10 : 0;
507 ds_add_packet(ds, dp); 625 ds_add_packet(ds, dp);
508 } 626 }
509 // we will not use audio index if we use -idx and have a video 627 // we will not use audio index if we use -idx and have a video
510 if(!demuxer->video->sh && index_mode == 2) 628 if(!demuxer->video->sh && index_mode == 2 && (unsigned)demuxer->audio->id < MAX_STREAMS)
511 while (timestamp > priv->index_table[demuxer->audio->id][priv->current_apacket].timestamp) 629 while (priv->current_apacket + 1 < priv->index_table_size[demuxer->audio->id] &&
630 timestamp > priv->index_table[demuxer->audio->id][priv->current_apacket].timestamp)
512 priv->current_apacket += 1; 631 priv->current_apacket += 1;
513 632
514 return 1; 633 return 1;
515 } 634 }
516 635
704 if(len){ 823 if(len){
705 printf("\n******** !!!!!!!! BUG!! len=%d !!!!!!!!!!! ********\n",len); 824 printf("\n******** !!!!!!!! BUG!! len=%d !!!!!!!!!!! ********\n",len);
706 if(len>0) stream_skip(demuxer->stream, len); 825 if(len>0) stream_skip(demuxer->stream, len);
707 } 826 }
708 } 827 }
709 if (index_mode == 1 || index_mode == 2) 828 if ((unsigned)demuxer->video->id < MAX_STREAMS)
710 while (timestamp > priv->index_table[demuxer->video->id][priv->current_vpacket + 1].timestamp) 829 while (priv->current_vpacket + 1 < priv->index_table_size[demuxer->video->id] &&
830 timestamp > priv->index_table[demuxer->video->id][priv->current_vpacket + 1].timestamp)
711 priv->current_vpacket += 1; 831 priv->current_vpacket += 1;
712 832
713 return 1; 833 return 1;
714 } 834 }
715 835
1242 } 1362 }
1243 1363
1244 if(demuxer->video->sh){ 1364 if(demuxer->video->sh){
1245 sh_video_t *sh=demuxer->video->sh; 1365 sh_video_t *sh=demuxer->video->sh;
1246 mp_msg(MSGT_DEMUX,MSGL_INFO,"VIDEO: %.4s [%08X,%08X] %dx%d (aspect %4.2f) %4.2f fps\n", 1366 mp_msg(MSGT_DEMUX,MSGL_INFO,"VIDEO: %.4s [%08X,%08X] %dx%d (aspect %4.2f) %4.2f fps\n",
1247 &sh->format,((unsigned int*)(sh->bih+1))[1],((unsigned int*)(sh->bih+1))[0], 1367 (char *)&(le2me_32(sh->format)),((unsigned int*)(sh->bih+1))[1],((unsigned int*)(sh->bih+1))[0],
1248 sh->disp_w,sh->disp_h,sh->aspect,sh->fps); 1368 sh->disp_w,sh->disp_h,sh->aspect,sh->fps);
1249 } 1369 }
1250 1370
1251 } 1371 }
1252 1372
1270 demux_stream_t *d_video = demuxer->video; 1390 demux_stream_t *d_video = demuxer->video;
1271 sh_audio_t *sh_audio = d_audio->sh; 1391 sh_audio_t *sh_audio = d_audio->sh;
1272 sh_video_t *sh_video = d_video->sh; 1392 sh_video_t *sh_video = d_video->sh;
1273 int vid = d_video->id, aid = d_audio->id; 1393 int vid = d_video->id, aid = d_audio->id;
1274 int next_offset = 0; 1394 int next_offset = 0;
1275 int rel_seek_frames = 0;
1276 int cur_timestamp = 0; 1395 int cur_timestamp = 0;
1277 int streams = 0; 1396 int streams = 0;
1397 int retried = 0;
1278 1398
1279 if ((index_mode != 1) && (index_mode != 2)) 1399 if ((index_mode != 1) && (index_mode != 2))
1280 return 0; 1400 return 0;
1281 1401
1282 if (sh_video) 1402 if (sh_video && (unsigned)vid < MAX_STREAMS && priv->index_table_size[vid])
1283 streams |= 1; 1403 streams |= 1;
1284 if (sh_audio) 1404 if (sh_audio && (unsigned)aid < MAX_STREAMS && priv->index_table_size[aid])
1285 streams |= 2; 1405 streams |= 2;
1286 1406
1287 // printf("streams: %d\n", streams); 1407 // printf("streams: %d\n", streams);
1288 1408
1289 if (!streams) 1409 if (!streams)
1291 1411
1292 if (flags & 1) 1412 if (flags & 1)
1293 /* seek absolute */ 1413 /* seek absolute */
1294 priv->current_apacket = priv->current_vpacket = 0; 1414 priv->current_apacket = priv->current_vpacket = 0;
1295 1415
1296 if (index_mode == 1) { 1416 if ((streams & 1) && priv->current_vpacket >= priv->index_table_size[vid])
1417 priv->current_vpacket = priv->index_table_size[vid] - 1;
1418 if ((streams & 2) && priv->current_apacket >= priv->index_table_size[aid])
1419 priv->current_apacket = priv->index_table_size[aid] - 1;
1420
1421 // if (index_mode == 1 || index_mode == 2) {
1297 if (streams & 1) {// use the video index if we have one 1422 if (streams & 1) {// use the video index if we have one
1298 cur_timestamp = priv->index_table[vid][priv->current_vpacket].timestamp; 1423 cur_timestamp = priv->index_table[vid][priv->current_vpacket].timestamp;
1299 if (rel_seek_secs > 0) 1424 if (rel_seek_secs > 0)
1300 while ((priv->index_table[vid][priv->current_vpacket].timestamp - cur_timestamp) < rel_seek_secs * 1000){ 1425 while ((priv->index_table[vid][priv->current_vpacket].timestamp - cur_timestamp) < rel_seek_secs * 1000){
1301 priv->current_vpacket += 1; 1426 priv->current_vpacket += 1;
1302 if (priv->current_vpacket >= priv->index_table_size[vid]) { 1427 if (priv->current_vpacket >= priv->index_table_size[vid]) {
1303 priv->current_vpacket = priv->index_table_size[vid] - 1; 1428 priv->current_vpacket = priv->index_table_size[vid] - 1;
1304 break; 1429 if (!retried) {
1430 stream_seek(demuxer->stream, priv->index_table[vid][priv->current_vpacket].offset);
1431 add_index_segment(demuxer, vid, cur_timestamp + rel_seek_secs * 1000);
1432 retried = 1;
1433 }
1434 else
1435 break;
1305 } 1436 }
1306 } 1437 }
1307 else if (rel_seek_secs < 0) 1438 else if (rel_seek_secs < 0)
1308 while ((cur_timestamp - priv->index_table[vid][priv->current_vpacket].timestamp) < - rel_seek_secs * 1000){ 1439 while ((cur_timestamp - priv->index_table[vid][priv->current_vpacket].timestamp) < - rel_seek_secs * 1000){
1309 priv->current_vpacket -= 1; 1440 priv->current_vpacket -= 1;
1334 break; 1465 break;
1335 } 1466 }
1336 } 1467 }
1337 next_offset = priv->index_table[aid][priv->current_apacket].offset; 1468 next_offset = priv->index_table[aid][priv->current_apacket].offset;
1338 } 1469 }
1339 } 1470 // }
1340 else if (index_mode == 2) {
1341 /* flags & 2 ? */
1342 if (streams & 1)
1343 rel_seek_frames = (int)(sh_video->fps*rel_seek_secs);
1344 else if (streams & 2)
1345 rel_seek_frames = (int)(rel_seek_secs);
1346
1347 // printf("rel_seek_frames: %d\n", rel_seek_frames);
1348
1349 if (streams & 2)
1350 priv->current_apacket += rel_seek_frames;
1351 if (streams & 1)
1352 priv->current_vpacket += rel_seek_frames;
1353
1354 if (
1355 ((streams & 2) && (priv->current_apacket > priv->index_table_size[aid])) ||
1356 ((streams & 1) && (priv->current_vpacket > priv->index_table_size[vid])) )
1357 return 0;
1358
1359 /* both video and audio stream */
1360 if (streams == 3)
1361 {
1362 // if (priv->current_apacket > priv->current_vpacket)
1363 // {
1364 /* search keyframe */
1365 while (!(priv->index_table[vid][priv->current_vpacket].flags & 0x2))
1366 priv->current_vpacket++;
1367 next_offset = priv->index_table[vid][priv->current_vpacket].offset;
1368 priv->audio_need_keyframe = 1;
1369 priv->video_after_seek = 1;
1370 // }
1371 // else
1372 // {
1373 // next_offset = priv->index_table[aid][priv->current_apacket].offset;
1374 // }
1375 }
1376 else
1377 {
1378 if (streams & 1)
1379 {
1380 /* search keyframe */
1381 while (!(priv->index_table[vid][priv->current_vpacket].flags & 0x2))
1382 priv->current_vpacket++;
1383 next_offset = priv->index_table[vid][priv->current_vpacket].offset;
1384 }
1385 else if (streams & 2)
1386 {
1387 next_offset = priv->index_table[aid][priv->current_apacket].offset;
1388 }
1389 }
1390 }
1391 // printf("seek: pos: %d, current packets: a: %d, v: %d\n", 1471 // printf("seek: pos: %d, current packets: a: %d, v: %d\n",
1392 // next_offset, priv->current_apacket, priv->current_vpacket); 1472 // next_offset, priv->current_apacket, priv->current_vpacket);
1393 stream_seek(demuxer->stream, next_offset); 1473 if (next_offset)
1474 stream_seek(demuxer->stream, next_offset);
1394 1475
1395 demux_real_fill_buffer(demuxer); 1476 demux_real_fill_buffer(demuxer);
1396 if (sh_audio) 1477 if (sh_audio)
1397 resync_audio_stream(sh_audio); 1478 resync_audio_stream(sh_audio);
1398 return 1; 1479 return 1;