comparison mov.c @ 5788:8539cb618ae7 libavformat

Preallocate index entries in mov demuxer, huge speedup
author bcoudurier
date Tue, 09 Mar 2010 00:46:26 +0000
parents adf1ad73c63e
children dba191dda275
comparison
equal deleted inserted replaced
5787:667736f463b3 5788:8539cb618ae7
1460 unsigned int distance = 0; 1460 unsigned int distance = 0;
1461 int key_off = sc->keyframes && sc->keyframes[0] == 1; 1461 int key_off = sc->keyframes && sc->keyframes[0] == 1;
1462 1462
1463 current_dts -= sc->dts_shift; 1463 current_dts -= sc->dts_shift;
1464 1464
1465 if (sc->sample_count >= UINT_MAX / sizeof(*st->index_entries))
1466 return;
1467 st->index_entries = av_malloc(sc->sample_count*sizeof(*st->index_entries));
1468 if (!st->index_entries)
1469 return;
1470 st->index_entries_allocated_size = sc->sample_count*sizeof(*st->index_entries);
1471
1465 for (i = 0; i < sc->chunk_count; i++) { 1472 for (i = 0; i < sc->chunk_count; i++) {
1466 current_offset = sc->chunk_offsets[i]; 1473 current_offset = sc->chunk_offsets[i];
1467 if (stsc_index + 1 < sc->stsc_count && 1474 if (stsc_index + 1 < sc->stsc_count &&
1468 i + 1 == sc->stsc_data[stsc_index + 1].first) 1475 i + 1 == sc->stsc_data[stsc_index + 1].first)
1469 stsc_index++; 1476 stsc_index++;
1486 if (keyframe) 1493 if (keyframe)
1487 distance = 0; 1494 distance = 0;
1488 sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample]; 1495 sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
1489 if(sc->pseudo_stream_id == -1 || 1496 if(sc->pseudo_stream_id == -1 ||
1490 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) { 1497 sc->stsc_data[stsc_index].id - 1 == sc->pseudo_stream_id) {
1491 av_add_index_entry(st, current_offset, current_dts, sample_size, distance, 1498 AVIndexEntry *e = &st->index_entries[st->nb_index_entries++];
1492 keyframe ? AVINDEX_KEYFRAME : 0); 1499 e->pos = current_offset;
1500 e->timestamp = current_dts;
1501 e->size = sample_size;
1502 e->min_distance = distance;
1503 e->flags = keyframe ? AVINDEX_KEYFRAME : 0;
1493 dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", " 1504 dprintf(mov->fc, "AVIndex stream %d, sample %d, offset %"PRIx64", dts %"PRId64", "
1494 "size %d, distance %d, keyframe %d\n", st->index, current_sample, 1505 "size %d, distance %d, keyframe %d\n", st->index, current_sample,
1495 current_offset, current_dts, sample_size, distance, keyframe); 1506 current_offset, current_dts, sample_size, distance, keyframe);
1496 } 1507 }
1497 1508
1508 } 1519 }
1509 } 1520 }
1510 if (st->duration > 0) 1521 if (st->duration > 0)
1511 st->codec->bit_rate = stream_size*8*sc->time_scale/st->duration; 1522 st->codec->bit_rate = stream_size*8*sc->time_scale/st->duration;
1512 } else { 1523 } else {
1524 unsigned chunk_samples, total = 0;
1525
1526 // compute total chunk count
1527 for (i = 0; i < sc->stsc_count; i++) {
1528 unsigned count, chunk_count;
1529
1530 chunk_samples = sc->stsc_data[i].count;
1531 if (sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
1532 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
1533 return;
1534 }
1535
1536 if (sc->samples_per_frame >= 160) { // gsm
1537 count = chunk_samples / sc->samples_per_frame;
1538 } else if (sc->samples_per_frame > 1) {
1539 unsigned samples = (1024/sc->samples_per_frame)*sc->samples_per_frame;
1540 count = (chunk_samples+samples-1) / samples;
1541 } else {
1542 count = (chunk_samples+1023) / 1024;
1543 }
1544
1545 if (i < sc->stsc_count - 1)
1546 chunk_count = sc->stsc_data[i+1].first - sc->stsc_data[i].first;
1547 else
1548 chunk_count = sc->chunk_count - (sc->stsc_data[i].first - 1);
1549 total += chunk_count * count;
1550 }
1551
1552 dprintf(mov->fc, "chunk count %d\n", total);
1553 if (total >= UINT_MAX / sizeof(*st->index_entries))
1554 return;
1555 st->index_entries = av_malloc(total*sizeof(*st->index_entries));
1556 if (!st->index_entries)
1557 return;
1558 st->index_entries_allocated_size = total*sizeof(*st->index_entries);
1559
1560 // populate index
1513 for (i = 0; i < sc->chunk_count; i++) { 1561 for (i = 0; i < sc->chunk_count; i++) {
1514 unsigned chunk_samples;
1515
1516 current_offset = sc->chunk_offsets[i]; 1562 current_offset = sc->chunk_offsets[i];
1517 if (stsc_index + 1 < sc->stsc_count && 1563 if (stsc_index + 1 < sc->stsc_count &&
1518 i + 1 == sc->stsc_data[stsc_index + 1].first) 1564 i + 1 == sc->stsc_data[stsc_index + 1].first)
1519 stsc_index++; 1565 stsc_index++;
1520 chunk_samples = sc->stsc_data[stsc_index].count; 1566 chunk_samples = sc->stsc_data[stsc_index].count;
1521 1567
1522 if (sc->samples_per_frame && chunk_samples % sc->samples_per_frame) {
1523 av_log(mov->fc, AV_LOG_ERROR, "error unaligned chunk\n");
1524 return;
1525 }
1526
1527 while (chunk_samples > 0) { 1568 while (chunk_samples > 0) {
1569 AVIndexEntry *e;
1528 unsigned size, samples; 1570 unsigned size, samples;
1529 1571
1530 if (sc->samples_per_frame >= 160) { // gsm 1572 if (sc->samples_per_frame >= 160) { // gsm
1531 samples = sc->samples_per_frame; 1573 samples = sc->samples_per_frame;
1532 size = sc->bytes_per_frame; 1574 size = sc->bytes_per_frame;
1539 samples = FFMIN(1024, chunk_samples); 1581 samples = FFMIN(1024, chunk_samples);
1540 size = samples * sc->sample_size; 1582 size = samples * sc->sample_size;
1541 } 1583 }
1542 } 1584 }
1543 1585
1544 av_add_index_entry(st, current_offset, current_dts, size, 0, AVINDEX_KEYFRAME); 1586 if (st->nb_index_entries >= total) {
1587 av_log(mov->fc, AV_LOG_ERROR, "wrong chunk count %d\n", total);
1588 return;
1589 }
1590 e = &st->index_entries[st->nb_index_entries++];
1591 e->pos = current_offset;
1592 e->timestamp = current_dts;
1593 e->size = size;
1594 e->min_distance = 0;
1595 e->flags = AVINDEX_KEYFRAME;
1545 dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", " 1596 dprintf(mov->fc, "AVIndex stream %d, chunk %d, offset %"PRIx64", dts %"PRId64", "
1546 "size %d, duration %d\n", st->index, i, current_offset, current_dts, 1597 "size %d, duration %d\n", st->index, i, current_offset, current_dts,
1547 size, samples); 1598 size, samples);
1548 1599
1549 current_offset += size; 1600 current_offset += size;