SampleTable.cpp revision 801d27d4d76aa040e83c9d9a2286909fd6661b88
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        // already set
215        return ERROR_MALFORMED;
216    }
217
218    if (data_offset < 0) {
219        return ERROR_MALFORMED;
220    }
221
222    mSampleToChunkOffset = data_offset;
223
224    if (data_size < 8) {
225        return ERROR_MALFORMED;
226    }
227
228    uint8_t header[8];
229    if (mDataSource->readAt(
230                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
231        return ERROR_IO;
232    }
233
234    if (U32_AT(header) != 0) {
235        // Expected version = 0, flags = 0.
236        return ERROR_MALFORMED;
237    }
238
239    mNumSampleToChunkOffsets = U32_AT(&header[4]);
240
241    if ((data_size - 8) / 12 < mNumSampleToChunkOffsets) {
242        return ERROR_MALFORMED;
243    }
244
245    if ((uint64_t)SIZE_MAX / sizeof(SampleToChunkEntry) <=
246            (uint64_t)mNumSampleToChunkOffsets) {
247        ALOGE("Sample-to-chunk table size too large.");
248        return ERROR_OUT_OF_RANGE;
249    }
250
251    mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
252            sizeof(SampleToChunkEntry);
253    if (mTotalSize > kMaxTotalSize) {
254        ALOGE("Sample-to-chunk table size would make sample table too large.\n"
255              "    Requested sample-to-chunk table size = %llu\n"
256              "    Eventual sample table size >= %llu\n"
257              "    Allowed sample table size = %llu\n",
258              (unsigned long long)mNumSampleToChunkOffsets *
259                      sizeof(SampleToChunkEntry),
260              (unsigned long long)mTotalSize,
261              (unsigned long long)kMaxTotalSize);
262        return ERROR_OUT_OF_RANGE;
263    }
264
265    mSampleToChunkEntries =
266        new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
267    if (!mSampleToChunkEntries) {
268        ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
269                (unsigned long long)mNumSampleToChunkOffsets);
270        return ERROR_OUT_OF_RANGE;
271    }
272
273    if (mNumSampleToChunkOffsets == 0) {
274        return OK;
275    }
276
277    if ((off64_t)(SIZE_MAX - 8 -
278            ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
279            < mSampleToChunkOffset) {
280        return ERROR_MALFORMED;
281    }
282
283    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
284        uint8_t buffer[12];
285
286        if ((SIZE_MAX - 8 - (i * 12)) < (size_t)mSampleToChunkOffset) {
287            return ERROR_MALFORMED;
288        }
289
290        if (mDataSource->readAt(
291                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
292                != (ssize_t)sizeof(buffer)) {
293            return ERROR_IO;
294        }
295        // chunk index is 1 based in the spec.
296        if (U32_AT(buffer) < 1) {
297            ALOGE("b/23534160");
298            return ERROR_OUT_OF_RANGE;
299        }
300
301        // We want the chunk index to be 0-based.
302        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
303        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
304        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
305    }
306
307    return OK;
308}
309
310status_t SampleTable::setSampleSizeParams(
311        uint32_t type, off64_t data_offset, size_t data_size) {
312    if (mSampleSizeOffset >= 0) {
313        return ERROR_MALFORMED;
314    }
315
316    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
317
318    mSampleSizeOffset = data_offset;
319
320    if (data_size < 12) {
321        return ERROR_MALFORMED;
322    }
323
324    uint8_t header[12];
325    if (mDataSource->readAt(
326                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
327        return ERROR_IO;
328    }
329
330    if (U32_AT(header) != 0) {
331        // Expected version = 0, flags = 0.
332        return ERROR_MALFORMED;
333    }
334
335    mDefaultSampleSize = U32_AT(&header[4]);
336    mNumSampleSizes = U32_AT(&header[8]);
337    if (mNumSampleSizes > (UINT32_MAX - 12) / 16) {
338        ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
339        return ERROR_MALFORMED;
340    }
341
342    if (type == kSampleSizeType32) {
343        mSampleSizeFieldSize = 32;
344
345        if (mDefaultSampleSize != 0) {
346            return OK;
347        }
348
349        if (data_size < 12 + mNumSampleSizes * 4) {
350            return ERROR_MALFORMED;
351        }
352    } else {
353        if ((mDefaultSampleSize & 0xffffff00) != 0) {
354            // The high 24 bits are reserved and must be 0.
355            return ERROR_MALFORMED;
356        }
357
358        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
359        mDefaultSampleSize = 0;
360
361        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
362            && mSampleSizeFieldSize != 16) {
363            return ERROR_MALFORMED;
364        }
365
366        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
367            return ERROR_MALFORMED;
368        }
369    }
370
371    return OK;
372}
373
374status_t SampleTable::setTimeToSampleParams(
375        off64_t data_offset, size_t data_size) {
376    if (mHasTimeToSample || data_size < 8) {
377        return ERROR_MALFORMED;
378    }
379
380    uint8_t header[8];
381    if (mDataSource->readAt(
382                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
383        return ERROR_IO;
384    }
385
386    if (U32_AT(header) != 0) {
387        // Expected version = 0, flags = 0.
388        return ERROR_MALFORMED;
389    }
390
391    mTimeToSampleCount = U32_AT(&header[4]);
392    if ((uint64_t)mTimeToSampleCount >
393        (uint64_t)UINT32_MAX / (2 * sizeof(uint32_t))) {
394        // Choose this bound because
395        // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
396        //    time-to-sample entry in the time-to-sample table.
397        // 2) mTimeToSampleCount is the number of entries of the time-to-sample
398        //    table.
399        // 3) We hope that the table size does not exceed UINT32_MAX.
400        ALOGE("Time-to-sample table size too large.");
401        return ERROR_OUT_OF_RANGE;
402    }
403
404    // Note: At this point, we know that mTimeToSampleCount * 2 will not
405    // overflow because of the above condition.
406
407    uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
408    mTotalSize += allocSize;
409    if (mTotalSize > kMaxTotalSize) {
410        ALOGE("Time-to-sample table size would make sample table too large.\n"
411              "    Requested time-to-sample table size = %llu\n"
412              "    Eventual sample table size >= %llu\n"
413              "    Allowed sample table size = %llu\n",
414              (unsigned long long)allocSize,
415              (unsigned long long)mTotalSize,
416              (unsigned long long)kMaxTotalSize);
417        return ERROR_OUT_OF_RANGE;
418    }
419
420    mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
421    if (!mTimeToSample) {
422        ALOGE("Cannot allocate time-to-sample table with %llu entries.",
423                (unsigned long long)mTimeToSampleCount);
424        return ERROR_OUT_OF_RANGE;
425    }
426
427    if (mDataSource->readAt(data_offset + 8, mTimeToSample,
428            (size_t)allocSize) < (ssize_t)allocSize) {
429        ALOGE("Incomplete data read for time-to-sample table.");
430        return ERROR_IO;
431    }
432
433    for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
434        mTimeToSample[i] = ntohl(mTimeToSample[i]);
435    }
436
437    mHasTimeToSample = true;
438    return OK;
439}
440
441// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
442// contains signed values, however some software creates version 0 files that
443// contain signed values, so we're always treating the values as signed,
444// regardless of version.
445status_t SampleTable::setCompositionTimeToSampleParams(
446        off64_t data_offset, size_t data_size) {
447    ALOGI("There are reordered frames present.");
448
449    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
450        return ERROR_MALFORMED;
451    }
452
453    uint8_t header[8];
454    if (mDataSource->readAt(
455                data_offset, header, sizeof(header))
456            < (ssize_t)sizeof(header)) {
457        return ERROR_IO;
458    }
459
460    uint32_t flags = U32_AT(header);
461    uint32_t version = flags >> 24;
462    flags &= 0xffffff;
463
464    if ((version != 0 && version != 1) || flags != 0) {
465        // Expected version = 0 or 1, flags = 0.
466        return ERROR_MALFORMED;
467    }
468
469    size_t numEntries = U32_AT(&header[4]);
470
471    if (((SIZE_MAX / 8) - 1 < numEntries) || (data_size != (numEntries + 1) * 8)) {
472        return ERROR_MALFORMED;
473    }
474
475    mNumCompositionTimeDeltaEntries = numEntries;
476    uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
477    if (allocSize > SIZE_MAX) {
478        ALOGE("Composition-time-to-sample table size too large.");
479        return ERROR_OUT_OF_RANGE;
480    }
481
482    mTotalSize += allocSize;
483    if (mTotalSize > kMaxTotalSize) {
484        ALOGE("Composition-time-to-sample table would make sample table too large.\n"
485              "    Requested composition-time-to-sample table size = %llu\n"
486              "    Eventual sample table size >= %llu\n"
487              "    Allowed sample table size = %llu\n",
488              (unsigned long long)allocSize,
489              (unsigned long long)mTotalSize,
490              (unsigned long long)kMaxTotalSize);
491        return ERROR_OUT_OF_RANGE;
492    }
493
494    mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
495    if (!mCompositionTimeDeltaEntries) {
496        ALOGE("Cannot allocate composition-time-to-sample table with %llu "
497                "entries.", (unsigned long long)numEntries);
498        return ERROR_OUT_OF_RANGE;
499    }
500
501    if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
502            (size_t)allocSize) < (ssize_t)allocSize) {
503        delete[] mCompositionTimeDeltaEntries;
504        mCompositionTimeDeltaEntries = NULL;
505
506        return ERROR_IO;
507    }
508
509    for (size_t i = 0; i < 2 * numEntries; ++i) {
510        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
511    }
512
513    mCompositionDeltaLookup->setEntries(
514            mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
515
516    return OK;
517}
518
519status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
520    if (mSyncSampleOffset >= 0 || data_size < 8) {
521        return ERROR_MALFORMED;
522    }
523
524    mSyncSampleOffset = data_offset;
525
526    uint8_t header[8];
527    if (mDataSource->readAt(
528                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
529        return ERROR_IO;
530    }
531
532    if (U32_AT(header) != 0) {
533        // Expected version = 0, flags = 0.
534        return ERROR_MALFORMED;
535    }
536
537    mNumSyncSamples = U32_AT(&header[4]);
538
539    if (mNumSyncSamples < 2) {
540        ALOGV("Table of sync samples is empty or has only a single entry!");
541    }
542
543    uint64_t allocSize = (uint64_t)mNumSyncSamples * sizeof(uint32_t);
544    if (allocSize > SIZE_MAX) {
545        ALOGE("Sync sample table size too large.");
546        return ERROR_OUT_OF_RANGE;
547    }
548
549    mTotalSize += allocSize;
550    if (mTotalSize > kMaxTotalSize) {
551        ALOGE("Sync sample table size would make sample table too large.\n"
552              "    Requested sync sample table size = %llu\n"
553              "    Eventual sample table size >= %llu\n"
554              "    Allowed sample table size = %llu\n",
555              (unsigned long long)allocSize,
556              (unsigned long long)mTotalSize,
557              (unsigned long long)kMaxTotalSize);
558        return ERROR_OUT_OF_RANGE;
559    }
560
561    mSyncSamples = new (std::nothrow) uint32_t[mNumSyncSamples];
562    if (!mSyncSamples) {
563        ALOGE("Cannot allocate sync sample table with %llu entries.",
564                (unsigned long long)mNumSyncSamples);
565        return ERROR_OUT_OF_RANGE;
566    }
567
568    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples,
569            (size_t)allocSize) != (ssize_t)allocSize) {
570        return ERROR_IO;
571    }
572
573    for (size_t i = 0; i < mNumSyncSamples; ++i) {
574        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
575    }
576
577    return OK;
578}
579
580uint32_t SampleTable::countChunkOffsets() const {
581    return mNumChunkOffsets;
582}
583
584uint32_t SampleTable::countSamples() const {
585    return mNumSampleSizes;
586}
587
588status_t SampleTable::getMaxSampleSize(size_t *max_size) {
589    Mutex::Autolock autoLock(mLock);
590
591    *max_size = 0;
592
593    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
594        size_t sample_size;
595        status_t err = getSampleSize_l(i, &sample_size);
596
597        if (err != OK) {
598            return err;
599        }
600
601        if (sample_size > *max_size) {
602            *max_size = sample_size;
603        }
604    }
605
606    return OK;
607}
608
609uint32_t abs_difference(uint32_t time1, uint32_t time2) {
610    return time1 > time2 ? time1 - time2 : time2 - time1;
611}
612
613// static
614int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
615    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
616    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
617
618    if (a->mCompositionTime < b->mCompositionTime) {
619        return -1;
620    } else if (a->mCompositionTime > b->mCompositionTime) {
621        return 1;
622    }
623
624    return 0;
625}
626
627void SampleTable::buildSampleEntriesTable() {
628    Mutex::Autolock autoLock(mLock);
629
630    if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
631        if (mNumSampleSizes == 0) {
632            ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
633        }
634        return;
635    }
636
637    mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
638    if (mTotalSize > kMaxTotalSize) {
639        ALOGE("Sample entry table size would make sample table too large.\n"
640              "    Requested sample entry table size = %llu\n"
641              "    Eventual sample table size >= %llu\n"
642              "    Allowed sample table size = %llu\n",
643              (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
644              (unsigned long long)mTotalSize,
645              (unsigned long long)kMaxTotalSize);
646        return;
647    }
648
649    mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
650    if (!mSampleTimeEntries) {
651        ALOGE("Cannot allocate sample entry table with %llu entries.",
652                (unsigned long long)mNumSampleSizes);
653        return;
654    }
655
656    uint32_t sampleIndex = 0;
657    uint32_t sampleTime = 0;
658
659    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
660        uint32_t n = mTimeToSample[2 * i];
661        uint32_t delta = mTimeToSample[2 * i + 1];
662
663        for (uint32_t j = 0; j < n; ++j) {
664            if (sampleIndex < mNumSampleSizes) {
665                // Technically this should always be the case if the file
666                // is well-formed, but you know... there's (gasp) malformed
667                // content out there.
668
669                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
670
671                int32_t compTimeDelta =
672                    mCompositionDeltaLookup->getCompositionTimeOffset(
673                            sampleIndex);
674
675                if ((compTimeDelta < 0 && sampleTime <
676                        (compTimeDelta == INT32_MIN ?
677                                INT32_MAX : uint32_t(-compTimeDelta)))
678                        || (compTimeDelta > 0 &&
679                                sampleTime > UINT32_MAX - compTimeDelta)) {
680                    ALOGE("%u + %d would overflow, clamping",
681                            sampleTime, compTimeDelta);
682                    if (compTimeDelta < 0) {
683                        sampleTime = 0;
684                    } else {
685                        sampleTime = UINT32_MAX;
686                    }
687                    compTimeDelta = 0;
688                }
689
690                mSampleTimeEntries[sampleIndex].mCompositionTime =
691                        compTimeDelta > 0 ? sampleTime + compTimeDelta:
692                                sampleTime - (-compTimeDelta);
693            }
694
695            ++sampleIndex;
696            sampleTime += delta;
697        }
698    }
699
700    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
701          CompareIncreasingTime);
702}
703
704status_t SampleTable::findSampleAtTime(
705        uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
706        uint32_t *sample_index, uint32_t flags) {
707    buildSampleEntriesTable();
708
709    if (mSampleTimeEntries == NULL) {
710        return ERROR_OUT_OF_RANGE;
711    }
712
713    uint32_t left = 0;
714    uint32_t right_plus_one = mNumSampleSizes;
715    while (left < right_plus_one) {
716        uint32_t center = left + (right_plus_one - left) / 2;
717        uint64_t centerTime =
718            getSampleTime(center, scale_num, scale_den);
719
720        if (req_time < centerTime) {
721            right_plus_one = center;
722        } else if (req_time > centerTime) {
723            left = center + 1;
724        } else {
725            *sample_index = mSampleTimeEntries[center].mSampleIndex;
726            return OK;
727        }
728    }
729
730    uint32_t closestIndex = left;
731
732    if (closestIndex == mNumSampleSizes) {
733        if (flags == kFlagAfter) {
734            return ERROR_OUT_OF_RANGE;
735        }
736        flags = kFlagBefore;
737    } else if (closestIndex == 0) {
738        if (flags == kFlagBefore) {
739            // normally we should return out of range, but that is
740            // treated as end-of-stream.  instead return first sample
741            //
742            // return ERROR_OUT_OF_RANGE;
743        }
744        flags = kFlagAfter;
745    }
746
747    switch (flags) {
748        case kFlagBefore:
749        {
750            --closestIndex;
751            break;
752        }
753
754        case kFlagAfter:
755        {
756            // nothing to do
757            break;
758        }
759
760        default:
761        {
762            CHECK(flags == kFlagClosest);
763            // pick closest based on timestamp. use abs_difference for safety
764            if (abs_difference(
765                    getSampleTime(closestIndex, scale_num, scale_den), req_time) >
766                abs_difference(
767                    req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
768                --closestIndex;
769            }
770            break;
771        }
772    }
773
774    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
775    return OK;
776}
777
778status_t SampleTable::findSyncSampleNear(
779        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
780    Mutex::Autolock autoLock(mLock);
781
782    *sample_index = 0;
783
784    if (mSyncSampleOffset < 0) {
785        // All samples are sync-samples.
786        *sample_index = start_sample_index;
787        return OK;
788    }
789
790    if (mNumSyncSamples == 0) {
791        *sample_index = 0;
792        return OK;
793    }
794
795    uint32_t left = 0;
796    uint32_t right_plus_one = mNumSyncSamples;
797    while (left < right_plus_one) {
798        uint32_t center = left + (right_plus_one - left) / 2;
799        uint32_t x = mSyncSamples[center];
800
801        if (start_sample_index < x) {
802            right_plus_one = center;
803        } else if (start_sample_index > x) {
804            left = center + 1;
805        } else {
806            *sample_index = x;
807            return OK;
808        }
809    }
810
811    if (left == mNumSyncSamples) {
812        if (flags == kFlagAfter) {
813            ALOGE("tried to find a sync frame after the last one: %d", left);
814            return ERROR_OUT_OF_RANGE;
815        }
816        flags = kFlagBefore;
817    }
818    else if (left == 0) {
819        if (flags == kFlagBefore) {
820            ALOGE("tried to find a sync frame before the first one: %d", left);
821
822            // normally we should return out of range, but that is
823            // treated as end-of-stream.  instead seek to first sync
824            //
825            // return ERROR_OUT_OF_RANGE;
826        }
827        flags = kFlagAfter;
828    }
829
830    // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
831    switch (flags) {
832        case kFlagBefore:
833        {
834            --left;
835            break;
836        }
837        case kFlagAfter:
838        {
839            // nothing to do
840            break;
841        }
842        default:
843        {
844            // this route is not used, but implement it nonetheless
845            CHECK(flags == kFlagClosest);
846
847            status_t err = mSampleIterator->seekTo(start_sample_index);
848            if (err != OK) {
849                return err;
850            }
851            uint32_t sample_time = mSampleIterator->getSampleTime();
852
853            err = mSampleIterator->seekTo(mSyncSamples[left]);
854            if (err != OK) {
855                return err;
856            }
857            uint32_t upper_time = mSampleIterator->getSampleTime();
858
859            err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
860            if (err != OK) {
861                return err;
862            }
863            uint32_t lower_time = mSampleIterator->getSampleTime();
864
865            // use abs_difference for safety
866            if (abs_difference(upper_time, sample_time) >
867                abs_difference(sample_time, lower_time)) {
868                --left;
869            }
870            break;
871        }
872    }
873
874    *sample_index = mSyncSamples[left];
875    return OK;
876}
877
878status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
879    Mutex::Autolock autoLock(mLock);
880
881    if (mSyncSampleOffset < 0) {
882        // All samples are sync-samples.
883        *sample_index = 0;
884        return OK;
885    }
886
887    uint32_t bestSampleIndex = 0;
888    size_t maxSampleSize = 0;
889
890    static const size_t kMaxNumSyncSamplesToScan = 20;
891
892    // Consider the first kMaxNumSyncSamplesToScan sync samples and
893    // pick the one with the largest (compressed) size as the thumbnail.
894
895    size_t numSamplesToScan = mNumSyncSamples;
896    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
897        numSamplesToScan = kMaxNumSyncSamplesToScan;
898    }
899
900    for (size_t i = 0; i < numSamplesToScan; ++i) {
901        uint32_t x = mSyncSamples[i];
902
903        // Now x is a sample index.
904        size_t sampleSize;
905        status_t err = getSampleSize_l(x, &sampleSize);
906        if (err != OK) {
907            return err;
908        }
909
910        if (i == 0 || sampleSize > maxSampleSize) {
911            bestSampleIndex = x;
912            maxSampleSize = sampleSize;
913        }
914    }
915
916    *sample_index = bestSampleIndex;
917
918    return OK;
919}
920
921status_t SampleTable::getSampleSize_l(
922        uint32_t sampleIndex, size_t *sampleSize) {
923    return mSampleIterator->getSampleSizeDirect(
924            sampleIndex, sampleSize);
925}
926
927status_t SampleTable::getMetaDataForSample(
928        uint32_t sampleIndex,
929        off64_t *offset,
930        size_t *size,
931        uint32_t *compositionTime,
932        bool *isSyncSample,
933        uint32_t *sampleDuration) {
934    Mutex::Autolock autoLock(mLock);
935
936    status_t err;
937    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
938        return err;
939    }
940
941    if (offset) {
942        *offset = mSampleIterator->getSampleOffset();
943    }
944
945    if (size) {
946        *size = mSampleIterator->getSampleSize();
947    }
948
949    if (compositionTime) {
950        *compositionTime = mSampleIterator->getSampleTime();
951    }
952
953    if (isSyncSample) {
954        *isSyncSample = false;
955        if (mSyncSampleOffset < 0) {
956            // Every sample is a sync sample.
957            *isSyncSample = true;
958        } else {
959            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
960                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
961                ? mLastSyncSampleIndex : 0;
962
963            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
964                ++i;
965            }
966
967            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
968                *isSyncSample = true;
969            }
970
971            mLastSyncSampleIndex = i;
972        }
973    }
974
975    if (sampleDuration) {
976        *sampleDuration = mSampleIterator->getSampleDuration();
977    }
978
979    return OK;
980}
981
982int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
983    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
984}
985
986}  // namespace android
987
988