154
112
//{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', 'h', '6') }, /* DVCPRO HD 60i produced by FCP */
155
113
{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'p') }, /* DVCPRO50 PAL produced by FCP */
156
114
{ CODEC_ID_DVVIDEO, MKTAG('d', 'v', '5', 'n') }, /* DVCPRO50 NTSC produced by FCP */
115
{ CODEC_ID_DVVIDEO, MKTAG('A', 'V', 'd', 'v') }, /* AVID DV */
157
116
//{ CODEC_ID_JPEG2000, MKTAG('m', 'j', 'p', '2') }, /* JPEG 2000 produced by FCP */
117
{ CODEC_ID_RAWVIDEO, MKTAG('2', 'v', 'u', 'y') }, /* UNCOMPRESSED 8BIT 4:2:2 */
158
118
{ CODEC_ID_NONE, 0 },
161
121
static const CodecTag mov_audio_tags[] = {
162
122
{ CODEC_ID_PCM_S32BE, MKTAG('i', 'n', '3', '2') },
163
123
{ CODEC_ID_PCM_S24BE, MKTAG('i', 'n', '2', '4') },
164
/* { CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, *//* uncompressed */
124
{ CODEC_ID_PCM_S16BE, MKTAG('N', 'O', 'N', 'E') }, /* uncompressed */
165
125
{ CODEC_ID_PCM_S16BE, MKTAG('t', 'w', 'o', 's') }, /* 16 bits */
166
/* { CODEC_ID_PCM_S8, MKTAG('t', 'w', 'o', 's') },*/ /* 8 bits */
167
126
{ CODEC_ID_PCM_U8, MKTAG('r', 'a', 'w', ' ') }, /* 8 bits unsigned */
168
127
{ CODEC_ID_PCM_S16LE, MKTAG('s', 'o', 'w', 't') }, /* */
169
128
{ CODEC_ID_PCM_MULAW, MKTAG('u', 'l', 'a', 'w') }, /* */
170
129
{ CODEC_ID_PCM_ALAW, MKTAG('a', 'l', 'a', 'w') }, /* */
171
130
{ CODEC_ID_ADPCM_IMA_QT, MKTAG('i', 'm', 'a', '4') }, /* IMA-4 ADPCM */
131
{ CODEC_ID_ADPCM_MS, MKTAG('m', 's', 0x00, 0x02) }, /* MS ADPCM */
172
132
{ CODEC_ID_MACE3, MKTAG('M', 'A', 'C', '3') }, /* Macintosh Audio Compression and Expansion 3:1 */
173
133
{ CODEC_ID_MACE6, MKTAG('M', 'A', 'C', '6') }, /* Macintosh Audio Compression and Expansion 6:1 */
175
{ CODEC_ID_MP2, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
135
{ CODEC_ID_MP3, MKTAG('.', 'm', 'p', '3') }, /* MPEG layer 3 */ /* sample files at http://www.3ivx.com/showcase.html use this tag */
176
136
{ CODEC_ID_MP2, 0x6D730055 }, /* MPEG layer 3 */
177
137
{ CODEC_ID_MP2, 0x5500736D }, /* MPEG layer 3 *//* XXX: check endianness */
178
138
/* { CODEC_ID_OGG_VORBIS, MKTAG('O', 'g', 'g', 'S') }, *//* sample files at http://heroinewarrior.com/xmovie.php3 use this tag */
187
147
{ CODEC_ID_NONE, 0 },
190
/* map numeric codes from mdhd atom to ISO 639 */
191
/* cf. QTFileFormat.pdf p253, qtff.pdf p205 */
192
/* http://developer.apple.com/documentation/mac/Text/Text-368.html */
193
/* deprecated by putting the code as 3*5bit ascii */
194
static const char *mov_mdhd_language_map[] = {
196
"eng", "fra", "ger", "ita", "dut", "sve", "spa", "dan", "por", "nor",
197
"heb", "jpn", "ara", "fin", "gre", "ice", "mlt", "tur", "hr "/*scr*/, "chi"/*ace?*/,
198
"urd", "hin", "tha", "kor", "lit", "pol", "hun", "est", "lav", NULL,
199
"fo ", NULL, "rus", "chi", NULL, "iri", "alb", "ron", "ces", "slk",
200
"slv", "yid", "sr ", "mac", "bul", "ukr", "bel", "uzb", "kaz", "aze",
202
"aze", "arm", "geo", "mol", "kir", "tgk", "tuk", "mon", NULL, "pus",
203
"kur", "kas", "snd", "tib", "nep", "san", "mar", "ben", "asm", "guj",
204
"pa ", "ori", "mal", "kan", "tam", "tel", NULL, "bur", "khm", "lao",
206
"vie", "ind", "tgl", "may", "may", "amh", "tir", "orm", "som", "swa",
208
NULL, "run", NULL, "mlg", "epo", NULL, NULL, NULL, NULL, NULL,
210
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
211
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
212
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, "wel", "baq",
213
"cat", "lat", "que", "grn", "aym", "tat", "uig", "dzo", "jav"
216
150
/* the QuickTime file format is quite convoluted...
217
151
* it has lots of index tables, each indexing something in another one...
218
152
* Here we just use what is needed to read the chunks
1515
static void mov_build_index(MOVContext *mov, AVStream *st)
1517
MOVStreamContext *sc = st->priv_data;
1518
offset_t current_offset;
1519
int64_t current_dts = 0;
1525
if (sc->sample_sizes || st->codec->codec_type == CODEC_TYPE_VIDEO) {
1526
int keyframe, sample_size;
1527
int current_sample = 0;
1528
int stts_sample = 0;
1531
st->nb_frames = sc->sample_count;
1532
for (i = 0; i < sc->chunk_count; i++) {
1533
current_offset = sc->chunk_offsets[i];
1534
if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
1536
for (j = 0; j < sc->sample_to_chunk[stsc_index].count; j++) {
1537
keyframe = !sc->keyframe_count || current_sample + 1 == sc->keyframes[stss_index];
1540
if (stss_index + 1 < sc->keyframe_count)
1543
sample_size = sc->sample_size > 0 ? sc->sample_size : sc->sample_sizes[current_sample];
1544
dprintf("AVIndex stream %d, sample %d, offset %llx, dts %lld, size %d, distance %d, keyframe %d\n",
1545
st->index, current_sample, current_offset, current_dts, sample_size, distance, keyframe);
1546
av_add_index_entry(st, current_offset, current_dts, sample_size, distance, keyframe ? AVINDEX_KEYFRAME : 0);
1547
current_offset += sample_size;
1548
assert(sc->stts_data[stts_index].duration % sc->time_rate == 0);
1549
current_dts += sc->stts_data[stts_index].duration / sc->time_rate;
1552
if (current_sample + 1 < sc->sample_count)
1554
if (stts_index + 1 < sc->stts_count && stts_sample == sc->stts_data[stts_index].count) {
1560
} else { /* read whole chunk */
1561
int chunk_samples, chunk_size, chunk_duration;
1563
for (i = 0; i < sc->chunk_count; i++) {
1564
current_offset = sc->chunk_offsets[i];
1565
if (stsc_index + 1 < sc->sample_to_chunk_sz && i + 1 == sc->sample_to_chunk[stsc_index + 1].first)
1567
chunk_samples = sc->sample_to_chunk[stsc_index].count;
1568
/* get chunk size */
1569
if (sc->sample_size > 1 || st->codec->bits_per_sample == 8)
1570
chunk_size = chunk_samples * sc->sample_size;
1571
else if (sc->sample_size_v1.den > 0 && (chunk_samples * sc->sample_size_v1.num % sc->sample_size_v1.den == 0))
1572
chunk_size = chunk_samples * sc->sample_size_v1.num / sc->sample_size_v1.den;
1573
else { /* workaround to find nearest next chunk offset */
1574
chunk_size = INT_MAX;
1575
for (j = 0; j < mov->total_streams; j++) {
1576
MOVStreamContext *msc = mov->streams[j];
1578
for (k = msc->next_chunk; k < msc->chunk_count; k++) {
1579
if (msc->chunk_offsets[k] > current_offset && msc->chunk_offsets[k] - current_offset < chunk_size) {
1580
chunk_size = msc->chunk_offsets[k] - current_offset;
1581
msc->next_chunk = k;
1586
/* check for last chunk */
1587
if (chunk_size == INT_MAX)
1588
for (j = 0; j < mov->mdat_count; j++) {
1589
dprintf("mdat %d, offset %llx, size %lld, current offset %llx\n",
1590
j, mov->mdat_list[j].offset, mov->mdat_list[j].size, current_offset);
1591
if (mov->mdat_list[j].offset <= current_offset && mov->mdat_list[j].offset + mov->mdat_list[j].size > current_offset)
1592
chunk_size = mov->mdat_list[j].offset + mov->mdat_list[j].size - current_offset;
1594
assert(chunk_size != INT_MAX);
1595
for (j = 0; j < mov->total_streams; j++) {
1596
mov->streams[j]->next_chunk = 0;
1599
av_add_index_entry(st, current_offset, current_dts, chunk_size, 0, AVINDEX_KEYFRAME);
1600
/* get chunk duration */
1602
while (chunk_samples > 0) {
1603
if (chunk_samples < sc->stts_data[stts_index].count) {
1604
chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
1605
sc->stts_data[stts_index].count -= chunk_samples;
1608
chunk_duration += sc->stts_data[stts_index].duration * chunk_samples;
1609
chunk_samples -= sc->stts_data[stts_index].count;
1610
if (stts_index + 1 < sc->stts_count) {
1615
dprintf("AVIndex stream %d, chunk %d, offset %llx, dts %lld, size %d, duration %d\n",
1616
st->index, i, current_offset, current_dts, chunk_size, chunk_duration);
1617
assert(chunk_duration % sc->time_rate == 0);
1618
current_dts += chunk_duration / sc->time_rate;
1621
/* adjust sample count to avindex entries */
1622
sc->sample_count = st->nb_index_entries;
1669
1625
static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap)
1671
1627
MOVContext *mov = (MOVContext *) s->priv_data;
1672
1628
ByteIOContext *pb = &s->pb;
1674
1630
MOV_atom_t atom = { 0, 0, 0 };
1720
1665
assert(s->streams[i]->duration % sc->time_rate == 0);
1721
1666
s->streams[i]->duration /= sc->time_rate;
1724
1668
sc->ffindex = i;
1725
sc->is_ff_stream = 1;
1669
mov_build_index(mov, s->streams[i]);
1672
for(i=0; i<mov->total_streams; i++) {
1673
/* dont need those anymore */
1674
av_freep(&mov->streams[i]->chunk_offsets);
1675
av_freep(&mov->streams[i]->sample_to_chunk);
1676
av_freep(&mov->streams[i]->sample_sizes);
1677
av_freep(&mov->streams[i]->keyframes);
1678
av_freep(&mov->streams[i]->stts_data);
1680
av_freep(&mov->mdat_list);
1731
/* Yes, this is ugly... I didn't write the specs of QT :p */
1732
/* XXX:remove useless commented code sometime */
1733
1684
static int mov_read_packet(AVFormatContext *s, AVPacket *pkt)
1735
MOVContext *mov = (MOVContext *) s->priv_data;
1736
MOVStreamContext *sc;
1738
int64_t offset = INT64_MAX;
1686
MOVContext *mov = s->priv_data;
1687
MOVStreamContext *sc = 0;
1688
AVIndexEntry *sample = 0;
1739
1689
int64_t best_dts = INT64_MAX;
1741
int next_sample= -99;
1748
idx = sc->sample_to_chunk_index;
1750
if (idx < 0) return 0;
1751
dprintf("sc[ffid %d]->sample_size = %ld\n", sc->ffindex, sc->sample_size);
1752
//size = sc->sample_sizes[sc->current_sample];
1753
// that ain't working...
1754
//size = (sc->sample_size)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1755
size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1757
next_sample= sc->current_sample+1;
1759
sc->left_in_chunk--;
1761
if (sc->left_in_chunk <= 0)
1763
offset = mov->next_chunk_offset;
1764
/* extract the sample */
1771
if(offset == INT64_MAX)
1772
best_dts= INT64_MAX;
1773
for(i=0; i<mov->total_streams; i++) {
1774
MOVStreamContext *msc = mov->streams[i];
1776
if ((msc->next_chunk < msc->chunk_count) && msc->next_chunk >= 0){
1777
if (msc->sample_to_time_index < msc->stts_count && mov->ni) {
1779
int index= msc->sample_to_time_index;
1780
int sample= msc->sample_to_time_sample;
1781
int time= msc->sample_to_time_time;
1782
int duration = msc->stts_data[index].duration;
1783
int count = msc->stts_data[index].count;
1784
if (sample + count <= msc->current_sample) {
1786
time += count*duration;
1788
duration = msc->stts_data[index].duration;
1790
dts = time + (msc->current_sample - sample) * (int64_t)duration;
1791
dts = av_rescale(dts, AV_TIME_BASE, msc->time_scale);
1792
dprintf("stream: %d dts: %"PRId64" best_dts: %"PRId64" offset: %"PRId64"\n", i, dts, best_dts, offset);
1796
offset = msc->chunk_offsets[msc->next_chunk];
1799
if ((msc->chunk_offsets[msc->next_chunk] < offset)) {
1801
offset = msc->chunk_offsets[msc->next_chunk];
1806
if (!sc || offset==INT64_MAX)
1811
if(mov->next_chunk_offset < offset) { /* some meta data */
1812
url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1813
mov->next_chunk_offset = offset;
1816
if(!sc->is_ff_stream || (s->streams[sc->ffindex]->discard >= AVDISCARD_ALL)) {
1817
url_fskip(&s->pb, (offset - mov->next_chunk_offset));
1818
mov->next_chunk_offset = offset;
1823
/* now get the chunk size... */
1825
for(i=0; i<mov->total_streams; i++) {
1826
MOVStreamContext *msc = mov->streams[i];
1827
if ((msc->next_chunk < msc->chunk_count)
1828
&& msc->chunk_offsets[msc->next_chunk] - offset < size
1829
&& msc->chunk_offsets[msc->next_chunk] > offset)
1830
size = msc->chunk_offsets[msc->next_chunk] - offset;
1833
#ifdef MOV_MINOLTA_FIX
1834
//Make sure that size is according to sample_size (Needed by .mov files
1835
//created on a Minolta Dimage Xi where audio chunks contains waste data in the end)
1836
//Maybe we should really not only check sc->sample_size, but also sc->sample_sizes
1837
//but I have no such movies
1838
if (sc->sample_size > 0) {
1840
for(i=0; i<(sc->sample_to_chunk_sz); i++) {
1841
if( (sc->sample_to_chunk[i].first)<=(sc->next_chunk) )
1843
foundsize=sc->sample_to_chunk[i].count*sc->sample_size;
1845
dprintf("sample_to_chunk first=%ld count=%ld, id=%ld\n", sc->sample_to_chunk[i].first, sc->sample_to_chunk[i].count, sc->sample_to_chunk[i].id);
1847
if( (foundsize>0) && (foundsize<size) )
1852
#endif //MOV_MINOLTA_FIX
1854
idx = sc->sample_to_chunk_index;
1855
if (idx + 1 < sc->sample_to_chunk_sz && sc->next_chunk >= sc->sample_to_chunk[idx + 1].first)
1857
sc->sample_to_chunk_index = idx;
1858
/* split chunks into samples */
1859
if (sc->sample_size == 0 || sc->sample_size > 100) {
1860
if (idx >= 0 && sc->sample_to_chunk[idx].count != 1) {
1862
/* we'll have to get those samples before next chunk */
1863
sc->left_in_chunk = sc->sample_to_chunk[idx].count - 1;
1864
size = (sc->sample_size > 1)?sc->sample_size:sc->sample_sizes[sc->current_sample];
1867
next_sample= sc->current_sample+1;
1868
}else if(idx < sc->sample_to_chunk_sz){
1869
next_sample= sc->current_sample + sc->sample_to_chunk[idx].count;
1871
next_sample= sc->current_sample;
1874
dprintf("chunk: %"PRId64" -> %"PRId64" (%i)\n", offset, offset + size, size);
1875
if(size == 0x0FFFFFFF)
1876
size = mov->mdat_size + mov->mdat_offset - offset;
1881
url_fseek(&s->pb, offset, SEEK_SET);
1883
av_get_packet(&s->pb, pkt, size);
1692
for (i = 0; i < mov->total_streams; i++) {
1693
MOVStreamContext *msc = mov->streams[i];
1695
if (s->streams[i]->discard != AVDISCARD_ALL && msc->current_sample < msc->sample_count) {
1696
AVIndexEntry *current_sample = &s->streams[i]->index_entries[msc->current_sample];
1697
int64_t dts = av_rescale(current_sample->timestamp * (int64_t)msc->time_rate, AV_TIME_BASE, msc->time_scale);
1699
dprintf("stream %d, sample %ld, dts %lld\n", i, msc->current_sample, dts);
1700
if (dts < best_dts) {
1701
sample = current_sample;
1709
/* must be done just before reading, to avoid infinite loop on sample */
1710
sc->current_sample++;
1711
if (sample->pos >= url_fsize(&s->pb)) {
1712
av_log(mov->fc, AV_LOG_ERROR, "stream %d, offset 0x%llx: partial file\n", sc->ffindex, sample->pos);
1715
url_fseek(&s->pb, sample->pos, SEEK_SET);
1716
av_get_packet(&s->pb, pkt, sample->size);
1884
1717
pkt->stream_index = sc->ffindex;
1886
// If the keyframes table exists, mark any samples that are in the table as key frames.
1887
// If no table exists, treat very sample as a key frame.
1888
if (sc->keyframes) {
1890
b = sc->keyframe_count - 1;
1893
m = (a + b + 1) >> 1;
1894
if (sc->keyframes[m] > sc->current_sample) {
1718
pkt->dts = sample->timestamp;
1719
if (sc->ctts_data) {
1720
assert(sc->ctts_data[sc->sample_to_ctime_index].duration % sc->time_rate == 0);
1721
pkt->pts = pkt->dts + sc->ctts_data[sc->sample_to_ctime_index].duration / sc->time_rate;
1722
/* update ctts context */
1723
sc->sample_to_ctime_sample++;
1724
if (sc->sample_to_ctime_index < sc->ctts_count && sc->ctts_data[sc->sample_to_ctime_index].count == sc->sample_to_ctime_sample) {
1725
sc->sample_to_ctime_index++;
1726
sc->sample_to_ctime_sample = 0;
1901
if (sc->keyframes[a] == sc->current_sample)
1902
pkt->flags |= PKT_FLAG_KEY;
1905
pkt->flags |= PKT_FLAG_KEY;
1907
mov->next_chunk_offset = offset + size;
1909
/* find the corresponding dts */
1910
if (sc && sc->sample_to_time_index < sc->stts_count && pkt) {
1913
unsigned int duration = sc->stts_data[sc->sample_to_time_index].duration;
1914
count = sc->stts_data[sc->sample_to_time_index].count;
1915
if ((sc->sample_to_time_sample + count) <= sc->current_sample) {
1916
sc->sample_to_time_sample += count;
1917
sc->sample_to_time_time += count*duration;
1918
sc->sample_to_time_index ++;
1919
duration = sc->stts_data[sc->sample_to_time_index].duration;
1921
dts = sc->sample_to_time_time + (sc->current_sample - sc->sample_to_time_sample) * (int64_t)duration;
1922
/* find the corresponding pts */
1923
if (sc->sample_to_ctime_index < sc->ctts_count) {
1924
int duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1925
int count = sc->ctts_data[sc->sample_to_ctime_index].count;
1927
if ((sc->sample_to_ctime_sample + count) <= sc->current_sample) {
1928
sc->sample_to_ctime_sample += count;
1929
sc->sample_to_ctime_index ++;
1930
duration = sc->ctts_data[sc->sample_to_ctime_index].duration;
1932
pts = dts + duration;
1936
st= s->streams[ sc->ffindex ];
1937
assert(pts % st->time_base.num == 0);
1938
assert(dts % st->time_base.num == 0);
1940
pkt->pts = pts / st->time_base.num;
1941
pkt->dts = dts / st->time_base.num;
1942
dprintf("stream #%d smp #%ld dts = %"PRId64" pts = %"PRId64" (smp:%ld time:%"PRId64" idx:%d ent:%d count:%d dur:%d)\n"
1943
, pkt->stream_index, sc->current_sample-1, pkt->dts, pkt->pts
1944
, sc->sample_to_time_sample
1945
, sc->sample_to_time_time
1946
, sc->sample_to_time_index
1952
assert(next_sample>=0);
1953
sc->current_sample= next_sample;
1729
pkt->pts = pkt->dts;
1731
pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;
1732
pkt->pos = sample->pos;
1733
dprintf("stream %d, pts %lld, dts %lld, pos 0x%llx, duration %d\n", pkt->stream_index, pkt->pts, pkt->dts, pkt->pos, pkt->duration);
1958
#if defined(MOV_SEEK)
1960
* Seek method based on the one described in the Appendix C of QTFileFormat.pdf
1737
static int mov_seek_stream(AVStream *st, int64_t timestamp, int flags)
1739
MOVStreamContext *sc = st->priv_data;
1740
int sample, time_sample;
1743
sample = av_index_search_timestamp(st, timestamp, flags);
1744
dprintf("stream %d, timestamp %lld, sample %d\n", st->index, timestamp, sample);
1745
if (sample < 0) /* not sure what to do */
1747
sc->current_sample = sample;
1748
dprintf("stream %d, found sample %ld\n", st->index, sc->current_sample);
1749
/* adjust ctts index */
1750
if (sc->ctts_data) {
1752
for (i = 0; i < sc->ctts_count; i++) {
1753
time_sample += sc->ctts_data[i].count;
1754
if (time_sample >= sc->current_sample) {
1755
sc->sample_to_ctime_index = i;
1756
sc->sample_to_ctime_sample = time_sample - sc->current_sample;
1962
1764
static int mov_read_seek(AVFormatContext *s, int stream_index, int64_t sample_time, int flags)
1964
MOVContext* mov = (MOVContext *) s->priv_data;
1965
MOVStreamContext* sc;
1968
int32_t seek_sample, sample;
1972
int32_t left_in_chunk;
1973
int64_t chunk_file_offset;
1974
int64_t sample_file_offset;
1975
int32_t first_chunk_sample;
1976
int32_t sample_to_chunk_idx;
1977
int sample_to_time_index;
1978
long sample_to_time_sample = 0;
1979
uint64_t sample_to_time_time = 0;
1982
// Find the corresponding mov stream
1983
for (mov_idx = 0; mov_idx < mov->total_streams; mov_idx++)
1984
if (mov->streams[mov_idx]->ffindex == stream_index)
1986
if (mov_idx == mov->total_streams) {
1987
av_log(s, AV_LOG_ERROR, "mov: requested stream was not found in mov streams (idx=%i)\n", stream_index);
1990
sc = mov->streams[mov_idx];
1992
sample_time *= s->streams[stream_index]->time_base.num;
1994
// Step 1. Find the edit that contains the requested time (elst)
1995
if (sc->edit_count && 0) {
1996
// FIXME should handle edit list
1997
av_log(s, AV_LOG_ERROR, "mov: does not handle seeking in files that contain edit list (c:%d)\n", sc->edit_count);
2001
// Step 2. Find the corresponding sample using the Time-to-sample atom (stts) */
2002
dprintf("Searching for time %li in stream #%i (time_scale=%i)\n", (long)sample_time, mov_idx, sc->time_scale);
2003
start_time = 0; // FIXME use elst atom
2004
sample = 1; // sample are 0 based in table
2006
for (i = 0; i < sc->stts_count; i++) {
2007
count = sc->stts_data[i].count;
2008
duration = sc->stts_data[i].duration;
2009
if ((start_time + count*duration) > sample_time) {
2010
sample_to_time_time = start_time;
2011
sample_to_time_index = i;
2012
sample_to_time_sample = sample;
2013
sample += (sample_time - start_time) / duration;
2017
start_time += count * duration;
2019
sample_to_time_time = start_time;
2020
sample_to_time_index = i;
2021
/* NOTE: despite what qt doc say, the dt value (Display Time in qt vocabulary) computed with the stts atom
2022
is a decoding time stamp (dts) not a presentation time stamp. And as usual dts != pts for stream with b frames */
2024
dprintf("Found time %li at sample #%u\n", (long)sample_time, sample);
2025
if (sample > sc->sample_count) {
2026
av_log(s, AV_LOG_ERROR, "mov: sample pos is too high, unable to seek (req. sample=%i, sample count=%ld)\n", sample, sc->sample_count);
2030
// Step 3. Find the prior sync. sample using the Sync sample atom (stss)
2031
if (sc->keyframes) {
2033
b = sc->keyframe_count - 1;
2035
m = (a + b + 1) >> 1;
2036
if (sc->keyframes[m] > sample) {
2042
// for low latency prob: always use the previous keyframe, just uncomment the next line
2044
seek_sample = sc->keyframes[a];
2047
seek_sample = sample; // else all samples are key frames
2048
dprintf("Found nearest keyframe at sample #%i \n", seek_sample);
2050
// Step 4. Find the chunk of the sample using the Sample-to-chunk-atom (stsc)
2051
for (first_chunk_sample = 1, i = 0; i < (sc->sample_to_chunk_sz - 1); i++) {
2052
b = (sc->sample_to_chunk[i + 1].first - sc->sample_to_chunk[i].first) * sc->sample_to_chunk[i].count;
2053
if (seek_sample >= first_chunk_sample && seek_sample < (first_chunk_sample + b))
2055
first_chunk_sample += b;
2057
chunk = sc->sample_to_chunk[i].first + (seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count;
2058
left_in_chunk = sc->sample_to_chunk[i].count - (seek_sample - first_chunk_sample) % sc->sample_to_chunk[i].count;
2059
first_chunk_sample += ((seek_sample - first_chunk_sample) / sc->sample_to_chunk[i].count) * sc->sample_to_chunk[i].count;
2060
sample_to_chunk_idx = i;
2061
dprintf("Sample was found in chunk #%i at sample offset %i (idx %i)\n", chunk, seek_sample - first_chunk_sample, sample_to_chunk_idx);
2063
// Step 5. Find the offset of the chunk using the chunk offset atom
2064
if (!sc->chunk_offsets) {
2065
av_log(s, AV_LOG_ERROR, "mov: no chunk offset atom, unable to seek\n");
2068
if (chunk > sc->chunk_count) {
2069
av_log(s, AV_LOG_ERROR, "mov: chunk offset atom too short, unable to seek (req. chunk=%i, chunk count=%li)\n", chunk, sc->chunk_count);
2072
chunk_file_offset = sc->chunk_offsets[chunk - 1];
2073
dprintf("Chunk file offset is #%"PRIu64"\n", chunk_file_offset);
2075
// Step 6. Find the byte offset within the chunk using the sample size atom
2076
sample_file_offset = chunk_file_offset;
2077
if (sc->sample_size)
2078
sample_file_offset += (seek_sample - first_chunk_sample) * sc->sample_size;
2080
for (i = 0; i < (seek_sample - first_chunk_sample); i++) {
2081
sample_file_offset += sc->sample_sizes[first_chunk_sample + i - 1];
2084
dprintf("Sample file offset is #%"PRIu64"\n", sample_file_offset);
2086
// Step 6. Update the parser
2088
mov->next_chunk_offset = sample_file_offset;
2089
// Update current stream state
2090
sc->current_sample = seek_sample - 1; // zero based
2091
sc->left_in_chunk = left_in_chunk;
2092
sc->next_chunk = chunk; // +1 -1 (zero based)
2093
sc->sample_to_chunk_index = sample_to_chunk_idx;
2095
// Update other streams
2096
for (i = 0; i<mov->total_streams; i++) {
2097
MOVStreamContext *msc;
2098
if (i == mov_idx) continue;
2099
// Find the nearest 'next' chunk
2100
msc = mov->streams[i];
2102
b = msc->chunk_count - 1;
2104
m = (a + b + 1) >> 1;
2105
if (msc->chunk_offsets[m] > chunk_file_offset) {
2111
msc->next_chunk = a;
2112
if (msc->chunk_offsets[a] < chunk_file_offset && a < (msc->chunk_count-1))
2114
dprintf("Nearest next chunk for stream #%i is #%li @%"PRId64"\n", i, msc->next_chunk+1, msc->chunk_offsets[msc->next_chunk]);
2116
// Compute sample count and index in the sample_to_chunk table (what a pity)
2117
msc->sample_to_chunk_index = 0;
2118
msc->current_sample = 0;
2119
for(; msc->sample_to_chunk_index < (msc->sample_to_chunk_sz - 1)
2120
&& msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first <= (1 + msc->next_chunk); msc->sample_to_chunk_index++) {
2121
msc->current_sample += (msc->sample_to_chunk[msc->sample_to_chunk_index + 1].first - msc->sample_to_chunk[msc->sample_to_chunk_index].first) \
2122
* msc->sample_to_chunk[msc->sample_to_chunk_index].count;
2124
msc->current_sample += (msc->next_chunk - (msc->sample_to_chunk[msc->sample_to_chunk_index].first - 1)) * sc->sample_to_chunk[msc->sample_to_chunk_index].count;
2125
msc->left_in_chunk = msc->sample_to_chunk[msc->sample_to_chunk_index].count - 1;
2126
// Find corresponding position in stts (used later to compute dts)
2129
for (msc->sample_to_time_index = 0; msc->sample_to_time_index < msc->stts_count; msc->sample_to_time_index++) {
2130
count = msc->stts_data[msc->sample_to_time_index].count;
2131
duration = msc->stts_data[msc->sample_to_time_index].duration;
2132
if ((sample + count - 1) > msc->current_sample) {
2133
msc->sample_to_time_time = start_time;
2134
msc->sample_to_time_sample = sample;
2138
start_time += count * duration;
2141
for (msc->sample_to_ctime_index = 0; msc->sample_to_ctime_index < msc->ctts_count; msc->sample_to_ctime_index++) {
2142
count = msc->ctts_data[msc->sample_to_ctime_index].count;
2143
duration = msc->ctts_data[msc->sample_to_ctime_index].duration;
2144
if ((sample + count - 1) > msc->current_sample) {
2145
msc->sample_to_ctime_sample = sample;
2150
dprintf("Next Sample for stream #%i is #%li @%li\n", i, msc->current_sample + 1, msc->sample_to_chunk_index + 1);
1767
int64_t seek_timestamp, timestamp;
1771
if (stream_index >= s->nb_streams)
1774
st = s->streams[stream_index];
1775
sample = mov_seek_stream(st, sample_time, flags);
1779
/* adjust seek timestamp to found sample timestamp */
1780
seek_timestamp = st->index_entries[sample].timestamp;
1782
for (i = 0; i < s->nb_streams; i++) {
1784
if (stream_index == i || st->discard == AVDISCARD_ALL)
1787
timestamp = av_rescale_q(seek_timestamp, s->streams[stream_index]->time_base, st->time_base);
1788
mov_seek_stream(st, timestamp, flags);
2156
1793
static int mov_read_close(AVFormatContext *s)