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