SampleTable.cpp revision 978a6cd08746164ee1f37405d55e0f0bed8f8c24
1/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "SampleTable"
18//#define LOG_NDEBUG 0
19#include <utils/Log.h>
20
21#include "include/SampleTable.h"
22#include "include/SampleIterator.h"
23
24#include <arpa/inet.h>
25
26#include <media/stagefright/foundation/ADebug.h>
27#include <media/stagefright/DataSource.h>
28#include <media/stagefright/Utils.h>
29
30/* TODO: remove after being merged into other branches */
31#ifndef UINT32_MAX
32#define UINT32_MAX       (4294967295U)
33#endif
34
35namespace android {
36
37// static
38const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
39// static
40const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
41// static
42const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
43// static
44const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
45
46////////////////////////////////////////////////////////////////////////////////
47
48struct SampleTable::CompositionDeltaLookup {
49    CompositionDeltaLookup();
50
51    void setEntries(
52            const int32_t *deltaEntries, size_t numDeltaEntries);
53
54    int32_t getCompositionTimeOffset(uint32_t sampleIndex);
55
56private:
57    Mutex mLock;
58
59    const int32_t *mDeltaEntries;
60    size_t mNumDeltaEntries;
61
62    size_t mCurrentDeltaEntry;
63    size_t mCurrentEntrySampleIndex;
64
65    DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
66};
67
68SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
69    : mDeltaEntries(NULL),
70      mNumDeltaEntries(0),
71      mCurrentDeltaEntry(0),
72      mCurrentEntrySampleIndex(0) {
73}
74
75void SampleTable::CompositionDeltaLookup::setEntries(
76        const int32_t *deltaEntries, size_t numDeltaEntries) {
77    Mutex::Autolock autolock(mLock);
78
79    mDeltaEntries = deltaEntries;
80    mNumDeltaEntries = numDeltaEntries;
81    mCurrentDeltaEntry = 0;
82    mCurrentEntrySampleIndex = 0;
83}
84
85int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
86        uint32_t sampleIndex) {
87    Mutex::Autolock autolock(mLock);
88
89    if (mDeltaEntries == NULL) {
90        return 0;
91    }
92
93    if (sampleIndex < mCurrentEntrySampleIndex) {
94        mCurrentDeltaEntry = 0;
95        mCurrentEntrySampleIndex = 0;
96    }
97
98    while (mCurrentDeltaEntry < mNumDeltaEntries) {
99        uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
100        if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
101            return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
102        }
103
104        mCurrentEntrySampleIndex += sampleCount;
105        ++mCurrentDeltaEntry;
106    }
107
108    return 0;
109}
110
111////////////////////////////////////////////////////////////////////////////////
112
113SampleTable::SampleTable(const sp<DataSource> &source)
114    : mDataSource(source),
115      mChunkOffsetOffset(-1),
116      mChunkOffsetType(0),
117      mNumChunkOffsets(0),
118      mSampleToChunkOffset(-1),
119      mNumSampleToChunkOffsets(0),
120      mSampleSizeOffset(-1),
121      mSampleSizeFieldSize(0),
122      mDefaultSampleSize(0),
123      mNumSampleSizes(0),
124      mHasTimeToSample(false),
125      mTimeToSampleCount(0),
126      mTimeToSample(NULL),
127      mSampleTimeEntries(NULL),
128      mCompositionTimeDeltaEntries(NULL),
129      mNumCompositionTimeDeltaEntries(0),
130      mCompositionDeltaLookup(new CompositionDeltaLookup),
131      mSyncSampleOffset(-1),
132      mNumSyncSamples(0),
133      mSyncSamples(NULL),
134      mLastSyncSampleIndex(0),
135      mSampleToChunkEntries(NULL),
136      mTotalSize(0) {
137    mSampleIterator = new SampleIterator(this);
138}
139
140SampleTable::~SampleTable() {
141    delete[] mSampleToChunkEntries;
142    mSampleToChunkEntries = NULL;
143
144    delete[] mSyncSamples;
145    mSyncSamples = NULL;
146
147    delete[] mTimeToSample;
148    mTimeToSample = NULL;
149
150    delete mCompositionDeltaLookup;
151    mCompositionDeltaLookup = NULL;
152
153    delete[] mCompositionTimeDeltaEntries;
154    mCompositionTimeDeltaEntries = NULL;
155
156    delete[] mSampleTimeEntries;
157    mSampleTimeEntries = NULL;
158
159    delete mSampleIterator;
160    mSampleIterator = NULL;
161}
162
163bool SampleTable::isValid() const {
164    return mChunkOffsetOffset >= 0
165        && mSampleToChunkOffset >= 0
166        && mSampleSizeOffset >= 0
167        && mHasTimeToSample;
168}
169
170status_t SampleTable::setChunkOffsetParams(
171        uint32_t type, off64_t data_offset, size_t data_size) {
172    if (mChunkOffsetOffset >= 0) {
173        return ERROR_MALFORMED;
174    }
175
176    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
177
178    mChunkOffsetOffset = data_offset;
179    mChunkOffsetType = type;
180
181    if (data_size < 8) {
182        return ERROR_MALFORMED;
183    }
184
185    uint8_t header[8];
186    if (mDataSource->readAt(
187                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
188        return ERROR_IO;
189    }
190
191    if (U32_AT(header) != 0) {
192        // Expected version = 0, flags = 0.
193        return ERROR_MALFORMED;
194    }
195
196    mNumChunkOffsets = U32_AT(&header[4]);
197
198    if (mChunkOffsetType == kChunkOffsetType32) {
199      if ((data_size - 8) / 4 < mNumChunkOffsets) {
200            return ERROR_MALFORMED;
201        }
202    } else {
203      if ((data_size - 8) / 8 < mNumChunkOffsets) {
204            return ERROR_MALFORMED;
205        }
206    }
207
208    return OK;
209}
210
211status_t SampleTable::setSampleToChunkParams(
212        off64_t data_offset, size_t data_size) {
213    if (mSampleToChunkOffset >= 0) {
214        return ERROR_MALFORMED;
215    }
216
217    mSampleToChunkOffset = data_offset;
218
219    if (data_size < 8) {
220        return ERROR_MALFORMED;
221    }
222
223    uint8_t header[8];
224    if (mDataSource->readAt(
225                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
226        return ERROR_IO;
227    }
228
229    if (U32_AT(header) != 0) {
230        // Expected version = 0, flags = 0.
231        return ERROR_MALFORMED;
232    }
233
234    mNumSampleToChunkOffsets = U32_AT(&header[4]);
235
236    if ((data_size - 8) / 12 < mNumSampleToChunkOffsets) {
237        return ERROR_MALFORMED;
238    }
239
240    if ((uint64_t)SIZE_MAX / sizeof(SampleToChunkEntry) <=
241            (uint64_t)mNumSampleToChunkOffsets) {
242        ALOGE("Sample-to-chunk table size too large.");
243        return ERROR_OUT_OF_RANGE;
244    }
245
246    mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
247            sizeof(SampleToChunkEntry);
248    if (mTotalSize > kMaxTotalSize) {
249        ALOGE("Sample-to-chunk table size would make sample table too large.\n"
250              "    Requested sample-to-chunk table size = %llu\n"
251              "    Eventual sample table size >= %llu\n"
252              "    Allowed sample table size = %llu\n",
253              (unsigned long long)mNumSampleToChunkOffsets *
254                      sizeof(SampleToChunkEntry),
255              (unsigned long long)mTotalSize,
256              (unsigned long long)kMaxTotalSize);
257        return ERROR_OUT_OF_RANGE;
258    }
259
260    mSampleToChunkEntries =
261        new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
262    if (!mSampleToChunkEntries) {
263        ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
264                (unsigned long long)mNumSampleToChunkOffsets);
265        return ERROR_OUT_OF_RANGE;
266    }
267
268    if (mNumSampleToChunkOffsets == 0) {
269        return OK;
270    }
271
272    if ((off64_t)(SIZE_MAX - 8 -
273            ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
274            < mSampleToChunkOffset) {
275        return ERROR_MALFORMED;
276    }
277
278    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
279        uint8_t buffer[12];
280
281        if ((off64_t)(SIZE_MAX - 8 - (i * 12)) < mSampleToChunkOffset) {
282            return ERROR_MALFORMED;
283        }
284
285        if (mDataSource->readAt(
286                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
287                != (ssize_t)sizeof(buffer)) {
288            return ERROR_IO;
289        }
290        // chunk index is 1 based in the spec.
291        if (U32_AT(buffer) < 1) {
292            ALOGE("b/23534160");
293            return ERROR_OUT_OF_RANGE;
294        }
295
296        // We want the chunk index to be 0-based.
297        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
298        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
299        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
300    }
301
302    return OK;
303}
304
305status_t SampleTable::setSampleSizeParams(
306        uint32_t type, off64_t data_offset, size_t data_size) {
307    if (mSampleSizeOffset >= 0) {
308        return ERROR_MALFORMED;
309    }
310
311    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
312
313    mSampleSizeOffset = data_offset;
314
315    if (data_size < 12) {
316        return ERROR_MALFORMED;
317    }
318
319    uint8_t header[12];
320    if (mDataSource->readAt(
321                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
322        return ERROR_IO;
323    }
324
325    if (U32_AT(header) != 0) {
326        // Expected version = 0, flags = 0.
327        return ERROR_MALFORMED;
328    }
329
330    mDefaultSampleSize = U32_AT(&header[4]);
331    mNumSampleSizes = U32_AT(&header[8]);
332    if (mNumSampleSizes > (UINT32_MAX - 12) / 16) {
333        ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
334        return ERROR_MALFORMED;
335    }
336
337    if (type == kSampleSizeType32) {
338        mSampleSizeFieldSize = 32;
339
340        if (mDefaultSampleSize != 0) {
341            return OK;
342        }
343
344        if (data_size < 12 + mNumSampleSizes * 4) {
345            return ERROR_MALFORMED;
346        }
347    } else {
348        if ((mDefaultSampleSize & 0xffffff00) != 0) {
349            // The high 24 bits are reserved and must be 0.
350            return ERROR_MALFORMED;
351        }
352
353        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
354        mDefaultSampleSize = 0;
355
356        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
357            && mSampleSizeFieldSize != 16) {
358            return ERROR_MALFORMED;
359        }
360
361        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
362            return ERROR_MALFORMED;
363        }
364    }
365
366    return OK;
367}
368
369status_t SampleTable::setTimeToSampleParams(
370        off64_t data_offset, size_t data_size) {
371    if (mHasTimeToSample || data_size < 8) {
372        return ERROR_MALFORMED;
373    }
374
375    uint8_t header[8];
376    if (mDataSource->readAt(
377                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
378        return ERROR_IO;
379    }
380
381    if (U32_AT(header) != 0) {
382        // Expected version = 0, flags = 0.
383        return ERROR_MALFORMED;
384    }
385
386    mTimeToSampleCount = U32_AT(&header[4]);
387    if ((uint64_t)mTimeToSampleCount >
388        (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) {
389        // Choose this bound because
390        // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
391        //    time-to-sample entry in the time-to-sample table.
392        // 2) mTimeToSampleCount is the number of entries of the time-to-sample
393        //    table.
394        // 3) We hope that the table size does not exceed UINT32_MAX.
395        ALOGE("Time-to-sample table size too large.");
396        return ERROR_OUT_OF_RANGE;
397    }
398
399    // Note: At this point, we know that mTimeToSampleCount * 2 will not
400    // overflow because of the above condition.
401
402    uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
403    mTotalSize += allocSize;
404    if (mTotalSize > kMaxTotalSize) {
405        ALOGE("Time-to-sample table size would make sample table too large.\n"
406              "    Requested time-to-sample table size = %llu\n"
407              "    Eventual sample table size >= %llu\n"
408              "    Allowed sample table size = %llu\n",
409              (unsigned long long)allocSize,
410              (unsigned long long)mTotalSize,
411              (unsigned long long)kMaxTotalSize);
412        return ERROR_OUT_OF_RANGE;
413    }
414
415    mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
416    if (!mTimeToSample) {
417        ALOGE("Cannot allocate time-to-sample table with %llu entries.",
418                (unsigned long long)mTimeToSampleCount);
419        return ERROR_OUT_OF_RANGE;
420    }
421
422    if (mDataSource->readAt(data_offset + 8, mTimeToSample,
423            (size_t)allocSize) < (ssize_t)allocSize) {
424        ALOGE("Incomplete data read for time-to-sample table.");
425        return ERROR_IO;
426    }
427
428    for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
429        mTimeToSample[i] = ntohl(mTimeToSample[i]);
430    }
431
432    mHasTimeToSample = true;
433    return OK;
434}
435
436// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
437// contains signed values, however some software creates version 0 files that
438// contain signed values, so we're always treating the values as signed,
439// regardless of version.
440status_t SampleTable::setCompositionTimeToSampleParams(
441        off64_t data_offset, size_t data_size) {
442    ALOGI("There are reordered frames present.");
443
444    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
445        return ERROR_MALFORMED;
446    }
447
448    uint8_t header[8];
449    if (mDataSource->readAt(
450                data_offset, header, sizeof(header))
451            < (ssize_t)sizeof(header)) {
452        return ERROR_IO;
453    }
454
455    uint32_t flags = U32_AT(header);
456    uint32_t version = flags >> 24;
457    flags &= 0xffffff;
458
459    if ((version != 0 && version != 1) || flags != 0) {
460        // Expected version = 0 or 1, flags = 0.
461        return ERROR_MALFORMED;
462    }
463
464    size_t numEntries = U32_AT(&header[4]);
465
466    if (((SIZE_MAX / 8) - 1 < numEntries) || (data_size != (numEntries + 1) * 8)) {
467        return ERROR_MALFORMED;
468    }
469
470    mNumCompositionTimeDeltaEntries = numEntries;
471    uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
472    if (allocSize > SIZE_MAX) {
473        ALOGE("Composition-time-to-sample table size too large.");
474        return ERROR_OUT_OF_RANGE;
475    }
476
477    mTotalSize += allocSize;
478    if (mTotalSize > kMaxTotalSize) {
479        ALOGE("Composition-time-to-sample table would make sample table too large.\n"
480              "    Requested composition-time-to-sample table size = %llu\n"
481              "    Eventual sample table size >= %llu\n"
482              "    Allowed sample table size = %llu\n",
483              (unsigned long long)allocSize,
484              (unsigned long long)mTotalSize,
485              (unsigned long long)kMaxTotalSize);
486        return ERROR_OUT_OF_RANGE;
487    }
488
489    mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
490    if (!mCompositionTimeDeltaEntries) {
491        ALOGE("Cannot allocate composition-time-to-sample table with %llu "
492                "entries.", (unsigned long long)numEntries);
493        return ERROR_OUT_OF_RANGE;
494    }
495
496    if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
497            (size_t)allocSize) < (ssize_t)allocSize) {
498        delete[] mCompositionTimeDeltaEntries;
499        mCompositionTimeDeltaEntries = NULL;
500
501        return ERROR_IO;
502    }
503
504    for (size_t i = 0; i < 2 * numEntries; ++i) {
505        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
506    }
507
508    mCompositionDeltaLookup->setEntries(
509            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
510
511    return OK;
512}
513
514status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
515    if (mSyncSampleOffset >= 0 || data_size < 8) {
516        return ERROR_MALFORMED;
517    }
518
519    mSyncSampleOffset = data_offset;
520
521    uint8_t header[8];
522    if (mDataSource->readAt(
523                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
524        return ERROR_IO;
525    }
526
527    if (U32_AT(header) != 0) {
528        // Expected version = 0, flags = 0.
529        return ERROR_MALFORMED;
530    }
531
532    mNumSyncSamples = U32_AT(&header[4]);
533
534    if (mNumSyncSamples < 2) {
535        ALOGV("Table of sync samples is empty or has only a single entry!");
536    }
537
538    uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
539    if (allocSize > SIZE_MAX) {
540        ALOGE("Sync sample table size too large.");
541        return ERROR_OUT_OF_RANGE;
542    }
543
544    mTotalSize += allocSize;
545    if (mTotalSize > kMaxTotalSize) {
546        ALOGE("Sync sample table size would make sample table too large.\n"
547              "    Requested sync sample table size = %llu\n"
548              "    Eventual sample table size >= %llu\n"
549              "    Allowed sample table size = %llu\n",
550              (unsigned long long)allocSize,
551              (unsigned long long)mTotalSize,
552              (unsigned long long)kMaxTotalSize);
553        return ERROR_OUT_OF_RANGE;
554    }
555
556    mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples];
557    if (!mSyncSamples) {
558        ALOGE("Cannot allocate sync sample table with %llu entries.",
559                (unsigned long long)mNumSyncSamples);
560        return ERROR_OUT_OF_RANGE;
561    }
562
563    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples,
564            (size_t)allocSize) != (ssize_t)allocSize) {
565        return ERROR_IO;
566    }
567
568    for (size_t i = 0; i < mNumSyncSamples; ++i) {
569        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
570    }
571
572    return OK;
573}
574
575uint32_t SampleTable::countChunkOffsets() const {
576    return mNumChunkOffsets;
577}
578
579uint32_t SampleTable::countSamples() const {
580    return mNumSampleSizes;
581}
582
583status_t SampleTable::getMaxSampleSize(size_t *max_size) {
584    Mutex::Autolock autoLock(mLock);
585
586    *max_size = 0;
587
588    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
589        size_t sample_size;
590        status_t err = getSampleSize_l(i, &sample_size);
591
592        if (err != OK) {
593            return err;
594        }
595
596        if (sample_size > *max_size) {
597            *max_size = sample_size;
598        }
599    }
600
601    return OK;
602}
603
604uint32_t abs_difference(uint32_t time1, uint32_t time2) {
605    return time1 > time2 ? time1 - time2 : time2 - time1;
606}
607
608// static
609int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
610    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
611    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
612
613    if (a->mCompositionTime < b->mCompositionTime) {
614        return -1;
615    } else if (a->mCompositionTime > b->mCompositionTime) {
616        return 1;
617    }
618
619    return 0;
620}
621
622void SampleTable::buildSampleEntriesTable() {
623    Mutex::Autolock autoLock(mLock);
624
625    if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
626        if (mNumSampleSizes == 0) {
627            ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
628        }
629        return;
630    }
631
632    mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
633    if (mTotalSize > kMaxTotalSize) {
634        ALOGE("Sample entry table size would make sample table too large.\n"
635              "    Requested sample entry table size = %llu\n"
636              "    Eventual sample table size >= %llu\n"
637              "    Allowed sample table size = %llu\n",
638              (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
639              (unsigned long long)mTotalSize,
640              (unsigned long long)kMaxTotalSize);
641        return;
642    }
643
644    mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
645    if (!mSampleTimeEntries) {
646        ALOGE("Cannot allocate sample entry table with %llu entries.",
647                (unsigned long long)mNumSampleSizes);
648        return;
649    }
650
651    uint32_t sampleIndex = 0;
652    uint32_t sampleTime = 0;
653
654    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
655        uint32_t n = mTimeToSample[2 * i];
656        uint32_t delta = mTimeToSample[2 * i + 1];
657
658        for (uint32_t j = 0; j < n; ++j) {
659            if (sampleIndex < mNumSampleSizes) {
660                // Technically this should always be the case if the file
661                // is well-formed, but you know... there's (gasp) malformed
662                // content out there.
663
664                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
665
666                int32_t compTimeDelta =
667                    mCompositionDeltaLookup->getCompositionTimeOffset(
668                            sampleIndex);
669
670                if ((compTimeDelta < 0 && sampleTime <
671                        (compTimeDelta == INT32_MIN ?
672                                INT32_MAX : uint32_t(-compTimeDelta)))
673                        || (compTimeDelta > 0 &&
674                                sampleTime > UINT32_MAX - compTimeDelta)) {
675                    ALOGE("%u + %d would overflow, clamping",
676                            sampleTime, compTimeDelta);
677                    if (compTimeDelta < 0) {
678                        sampleTime = 0;
679                    } else {
680                        sampleTime = UINT32_MAX;
681                    }
682                    compTimeDelta = 0;
683                }
684
685                mSampleTimeEntries[sampleIndex].mCompositionTime =
686                        compTimeDelta > 0 ? sampleTime + compTimeDelta:
687                                sampleTime - (-compTimeDelta);
688            }
689
690            ++sampleIndex;
691            sampleTime += delta;
692        }
693    }
694
695    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
696          CompareIncreasingTime);
697}
698
699status_t SampleTable::findSampleAtTime(
700        uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
701        uint32_t *sample_index, uint32_t flags) {
702    buildSampleEntriesTable();
703
704    if (mSampleTimeEntries == NULL) {
705        return ERROR_OUT_OF_RANGE;
706    }
707
708    uint32_t left = 0;
709    uint32_t right_plus_one = mNumSampleSizes;
710    while (left < right_plus_one) {
711        uint32_t center = left + (right_plus_one - left) / 2;
712        uint64_t centerTime =
713            getSampleTime(center, scale_num, scale_den);
714
715        if (req_time < centerTime) {
716            right_plus_one = center;
717        } else if (req_time > centerTime) {
718            left = center + 1;
719        } else {
720            *sample_index = mSampleTimeEntries[center].mSampleIndex;
721            return OK;
722        }
723    }
724
725    uint32_t closestIndex = left;
726
727    if (closestIndex == mNumSampleSizes) {
728        if (flags == kFlagAfter) {
729            return ERROR_OUT_OF_RANGE;
730        }
731        flags = kFlagBefore;
732    } else if (closestIndex == 0) {
733        if (flags == kFlagBefore) {
734            // normally we should return out of range, but that is
735            // treated as end-of-stream.  instead return first sample
736            //
737            // return ERROR_OUT_OF_RANGE;
738        }
739        flags = kFlagAfter;
740    }
741
742    switch (flags) {
743        case kFlagBefore:
744        {
745            --closestIndex;
746            break;
747        }
748
749        case kFlagAfter:
750        {
751            // nothing to do
752            break;
753        }
754
755        default:
756        {
757            CHECK(flags == kFlagClosest);
758            // pick closest based on timestamp. use abs_difference for safety
759            if (abs_difference(
760                    getSampleTime(closestIndex, scale_num, scale_den), req_time) >
761                abs_difference(
762                    req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
763                --closestIndex;
764            }
765            break;
766        }
767    }
768
769    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
770    return OK;
771}
772
773status_t SampleTable::findSyncSampleNear(
774        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
775    Mutex::Autolock autoLock(mLock);
776
777    *sample_index = 0;
778
779    if (mSyncSampleOffset < 0) {
780        // All samples are sync-samples.
781        *sample_index = start_sample_index;
782        return OK;
783    }
784
785    if (mNumSyncSamples == 0) {
786        *sample_index = 0;
787        return OK;
788    }
789
790    uint32_t left = 0;
791    uint32_t right_plus_one = mNumSyncSamples;
792    while (left < right_plus_one) {
793        uint32_t center = left + (right_plus_one - left) / 2;
794        uint32_t x = mSyncSamples[center];
795
796        if (start_sample_index < x) {
797            right_plus_one = center;
798        } else if (start_sample_index > x) {
799            left = center + 1;
800        } else {
801            *sample_index = x;
802            return OK;
803        }
804    }
805
806    if (left == mNumSyncSamples) {
807        if (flags == kFlagAfter) {
808            ALOGE("tried to find a sync frame after the last one: %d", left);
809            return ERROR_OUT_OF_RANGE;
810        }
811        flags = kFlagBefore;
812    }
813    else if (left == 0) {
814        if (flags == kFlagBefore) {
815            ALOGE("tried to find a sync frame before the first one: %d", left);
816
817            // normally we should return out of range, but that is
818            // treated as end-of-stream.  instead seek to first sync
819            //
820            // return ERROR_OUT_OF_RANGE;
821        }
822        flags = kFlagAfter;
823    }
824
825    // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
826    switch (flags) {
827        case kFlagBefore:
828        {
829            --left;
830            break;
831        }
832        case kFlagAfter:
833        {
834            // nothing to do
835            break;
836        }
837        default:
838        {
839            // this route is not used, but implement it nonetheless
840            CHECK(flags == kFlagClosest);
841
842            status_t err = mSampleIterator->seekTo(start_sample_index);
843            if (err != OK) {
844                return err;
845            }
846            uint32_t sample_time = mSampleIterator->getSampleTime();
847
848            err = mSampleIterator->seekTo(mSyncSamples[left]);
849            if (err != OK) {
850                return err;
851            }
852            uint32_t upper_time = mSampleIterator->getSampleTime();
853
854            err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
855            if (err != OK) {
856                return err;
857            }
858            uint32_t lower_time = mSampleIterator->getSampleTime();
859
860            // use abs_difference for safety
861            if (abs_difference(upper_time, sample_time) >
862                abs_difference(sample_time, lower_time)) {
863                --left;
864            }
865            break;
866        }
867    }
868
869    *sample_index = mSyncSamples[left];
870    return OK;
871}
872
873status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
874    Mutex::Autolock autoLock(mLock);
875
876    if (mSyncSampleOffset < 0) {
877        // All samples are sync-samples.
878        *sample_index = 0;
879        return OK;
880    }
881
882    uint32_t bestSampleIndex = 0;
883    size_t maxSampleSize = 0;
884
885    static const size_t kMaxNumSyncSamplesToScan = 20;
886
887    // Consider the first kMaxNumSyncSamplesToScan sync samples and
888    // pick the one with the largest (compressed) size as the thumbnail.
889
890    size_t numSamplesToScan = mNumSyncSamples;
891    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
892        numSamplesToScan = kMaxNumSyncSamplesToScan;
893    }
894
895    for (size_t i = 0; i < numSamplesToScan; ++i) {
896        uint32_t x = mSyncSamples[i];
897
898        // Now x is a sample index.
899        size_t sampleSize;
900        status_t err = getSampleSize_l(x, &sampleSize);
901        if (err != OK) {
902            return err;
903        }
904
905        if (i == 0 || sampleSize > maxSampleSize) {
906            bestSampleIndex = x;
907            maxSampleSize = sampleSize;
908        }
909    }
910
911    *sample_index = bestSampleIndex;
912
913    return OK;
914}
915
916status_t SampleTable::getSampleSize_l(
917        uint32_t sampleIndex, size_t *sampleSize) {
918    return mSampleIterator->getSampleSizeDirect(
919            sampleIndex, sampleSize);
920}
921
922status_t SampleTable::getMetaDataForSample(
923        uint32_t sampleIndex,
924        off64_t *offset,
925        size_t *size,
926        uint32_t *compositionTime,
927        bool *isSyncSample,
928        uint32_t *sampleDuration) {
929    Mutex::Autolock autoLock(mLock);
930
931    status_t err;
932    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
933        return err;
934    }
935
936    if (offset) {
937        *offset = mSampleIterator->getSampleOffset();
938    }
939
940    if (size) {
941        *size = mSampleIterator->getSampleSize();
942    }
943
944    if (compositionTime) {
945        *compositionTime = mSampleIterator->getSampleTime();
946    }
947
948    if (isSyncSample) {
949        *isSyncSample = false;
950        if (mSyncSampleOffset < 0) {
951            // Every sample is a sync sample.
952            *isSyncSample = true;
953        } else {
954            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
955                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
956                ? mLastSyncSampleIndex : 0;
957
958            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
959                ++i;
960            }
961
962            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
963                *isSyncSample = true;
964            }
965
966            mLastSyncSampleIndex = i;
967        }
968    }
969
970    if (sampleDuration) {
971        *sampleDuration = mSampleIterator->getSampleDuration();
972    }
973
974    return OK;
975}
976
977int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
978    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
979}
980
981}  // namespace android
982
983