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