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    uint8_t header[8];
526    if (mDataSource->readAt(
527                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
528        return ERROR_IO;
529    }
530
531    if (U32_AT(header) != 0) {
532        // Expected version = 0, flags = 0.
533        return ERROR_MALFORMED;
534    }
535
536    uint32_t numSyncSamples = U32_AT(&header[4]);
537
538    if (numSyncSamples < 2) {
539        ALOGV("Table of sync samples is empty or has only a single entry!");
540    }
541
542    uint64_t allocSize = (uint64_t)numSyncSamples * sizeof(uint32_t);
543    if (allocSize > kMaxTotalSize) {
544        ALOGE("Sync sample table size too large.");
545        return ERROR_OUT_OF_RANGE;
546    }
547
548    mTotalSize += allocSize;
549    if (mTotalSize > kMaxTotalSize) {
550        ALOGE("Sync sample table size would make sample table too large.\n"
551              "    Requested sync sample table size = %llu\n"
552              "    Eventual sample table size >= %llu\n"
553              "    Allowed sample table size = %llu\n",
554              (unsigned long long)allocSize,
555              (unsigned long long)mTotalSize,
556              (unsigned long long)kMaxTotalSize);
557        return ERROR_OUT_OF_RANGE;
558    }
559
560    mSyncSamples = new (std::nothrow) uint32_t[numSyncSamples];
561    if (!mSyncSamples) {
562        ALOGE("Cannot allocate sync sample table with %llu entries.",
563                (unsigned long long)numSyncSamples);
564        return ERROR_OUT_OF_RANGE;
565    }
566
567    if (mDataSource->readAt(data_offset + 8, mSyncSamples,
568            (size_t)allocSize) != (ssize_t)allocSize) {
569        delete[] mSyncSamples;
570        mSyncSamples = NULL;
571        return ERROR_IO;
572    }
573
574    for (size_t i = 0; i < numSyncSamples; ++i) {
575        if (mSyncSamples[i] == 0) {
576            ALOGE("b/32423862, unexpected zero value in stss");
577            continue;
578        }
579        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
580    }
581
582    mSyncSampleOffset = data_offset;
583    mNumSyncSamples = numSyncSamples;
584
585    return OK;
586}
587
588uint32_t SampleTable::countChunkOffsets() const {
589    return mNumChunkOffsets;
590}
591
592uint32_t SampleTable::countSamples() const {
593    return mNumSampleSizes;
594}
595
596status_t SampleTable::getMaxSampleSize(size_t *max_size) {
597    Mutex::Autolock autoLock(mLock);
598
599    *max_size = 0;
600
601    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
602        size_t sample_size;
603        status_t err = getSampleSize_l(i, &sample_size);
604
605        if (err != OK) {
606            return err;
607        }
608
609        if (sample_size > *max_size) {
610            *max_size = sample_size;
611        }
612    }
613
614    return OK;
615}
616
617uint32_t abs_difference(uint32_t time1, uint32_t time2) {
618    return time1 > time2 ? time1 - time2 : time2 - time1;
619}
620
621// static
622int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
623    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
624    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
625
626    if (a->mCompositionTime < b->mCompositionTime) {
627        return -1;
628    } else if (a->mCompositionTime > b->mCompositionTime) {
629        return 1;
630    }
631
632    return 0;
633}
634
635void SampleTable::buildSampleEntriesTable() {
636    Mutex::Autolock autoLock(mLock);
637
638    if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
639        if (mNumSampleSizes == 0) {
640            ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
641        }
642        return;
643    }
644
645    mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
646    if (mTotalSize > kMaxTotalSize) {
647        ALOGE("Sample entry table size would make sample table too large.\n"
648              "    Requested sample entry table size = %llu\n"
649              "    Eventual sample table size >= %llu\n"
650              "    Allowed sample table size = %llu\n",
651              (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
652              (unsigned long long)mTotalSize,
653              (unsigned long long)kMaxTotalSize);
654        return;
655    }
656
657    mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
658    if (!mSampleTimeEntries) {
659        ALOGE("Cannot allocate sample entry table with %llu entries.",
660                (unsigned long long)mNumSampleSizes);
661        return;
662    }
663
664    uint32_t sampleIndex = 0;
665    uint32_t sampleTime = 0;
666
667    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
668        uint32_t n = mTimeToSample[2 * i];
669        uint32_t delta = mTimeToSample[2 * i + 1];
670
671        for (uint32_t j = 0; j < n; ++j) {
672            if (sampleIndex < mNumSampleSizes) {
673                // Technically this should always be the case if the file
674                // is well-formed, but you know... there's (gasp) malformed
675                // content out there.
676
677                mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
678
679                int32_t compTimeDelta =
680                    mCompositionDeltaLookup->getCompositionTimeOffset(
681                            sampleIndex);
682
683                if ((compTimeDelta < 0 && sampleTime <
684                        (compTimeDelta == INT32_MIN ?
685                                INT32_MAX : uint32_t(-compTimeDelta)))
686                        || (compTimeDelta > 0 &&
687                                sampleTime > UINT32_MAX - compTimeDelta)) {
688                    ALOGE("%u + %d would overflow, clamping",
689                            sampleTime, compTimeDelta);
690                    if (compTimeDelta < 0) {
691                        sampleTime = 0;
692                    } else {
693                        sampleTime = UINT32_MAX;
694                    }
695                    compTimeDelta = 0;
696                }
697
698                mSampleTimeEntries[sampleIndex].mCompositionTime =
699                        compTimeDelta > 0 ? sampleTime + compTimeDelta:
700                                sampleTime - (-compTimeDelta);
701            }
702
703            ++sampleIndex;
704            if (sampleTime > UINT32_MAX - delta) {
705                ALOGE("%u + %u would overflow, clamping",
706                    sampleTime, delta);
707                sampleTime = UINT32_MAX;
708            } else {
709                sampleTime += delta;
710            }
711        }
712    }
713
714    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
715          CompareIncreasingTime);
716}
717
718status_t SampleTable::findSampleAtTime(
719        uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
720        uint32_t *sample_index, uint32_t flags) {
721    buildSampleEntriesTable();
722
723    if (mSampleTimeEntries == NULL) {
724        return ERROR_OUT_OF_RANGE;
725    }
726
727    uint32_t left = 0;
728    uint32_t right_plus_one = mNumSampleSizes;
729    while (left < right_plus_one) {
730        uint32_t center = left + (right_plus_one - left) / 2;
731        uint64_t centerTime =
732            getSampleTime(center, scale_num, scale_den);
733
734        if (req_time < centerTime) {
735            right_plus_one = center;
736        } else if (req_time > centerTime) {
737            left = center + 1;
738        } else {
739            *sample_index = mSampleTimeEntries[center].mSampleIndex;
740            return OK;
741        }
742    }
743
744    uint32_t closestIndex = left;
745
746    if (closestIndex == mNumSampleSizes) {
747        if (flags == kFlagAfter) {
748            return ERROR_OUT_OF_RANGE;
749        }
750        flags = kFlagBefore;
751    } else if (closestIndex == 0) {
752        if (flags == kFlagBefore) {
753            // normally we should return out of range, but that is
754            // treated as end-of-stream.  instead return first sample
755            //
756            // return ERROR_OUT_OF_RANGE;
757        }
758        flags = kFlagAfter;
759    }
760
761    switch (flags) {
762        case kFlagBefore:
763        {
764            --closestIndex;
765            break;
766        }
767
768        case kFlagAfter:
769        {
770            // nothing to do
771            break;
772        }
773
774        default:
775        {
776            CHECK(flags == kFlagClosest);
777            // pick closest based on timestamp. use abs_difference for safety
778            if (abs_difference(
779                    getSampleTime(closestIndex, scale_num, scale_den), req_time) >
780                abs_difference(
781                    req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
782                --closestIndex;
783            }
784            break;
785        }
786    }
787
788    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
789    return OK;
790}
791
792status_t SampleTable::findSyncSampleNear(
793        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
794    Mutex::Autolock autoLock(mLock);
795
796    *sample_index = 0;
797
798    if (mSyncSampleOffset < 0) {
799        // All samples are sync-samples.
800        *sample_index = start_sample_index;
801        return OK;
802    }
803
804    if (mNumSyncSamples == 0) {
805        *sample_index = 0;
806        return OK;
807    }
808
809    uint32_t left = 0;
810    uint32_t right_plus_one = mNumSyncSamples;
811    while (left < right_plus_one) {
812        uint32_t center = left + (right_plus_one - left) / 2;
813        uint32_t x = mSyncSamples[center];
814
815        if (start_sample_index < x) {
816            right_plus_one = center;
817        } else if (start_sample_index > x) {
818            left = center + 1;
819        } else {
820            *sample_index = x;
821            return OK;
822        }
823    }
824
825    if (left == mNumSyncSamples) {
826        if (flags == kFlagAfter) {
827            ALOGE("tried to find a sync frame after the last one: %d", left);
828            return ERROR_OUT_OF_RANGE;
829        }
830        flags = kFlagBefore;
831    }
832    else if (left == 0) {
833        if (flags == kFlagBefore) {
834            ALOGE("tried to find a sync frame before the first one: %d", left);
835
836            // normally we should return out of range, but that is
837            // treated as end-of-stream.  instead seek to first sync
838            //
839            // return ERROR_OUT_OF_RANGE;
840        }
841        flags = kFlagAfter;
842    }
843
844    // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
845    switch (flags) {
846        case kFlagBefore:
847        {
848            --left;
849            break;
850        }
851        case kFlagAfter:
852        {
853            // nothing to do
854            break;
855        }
856        default:
857        {
858            // this route is not used, but implement it nonetheless
859            CHECK(flags == kFlagClosest);
860
861            status_t err = mSampleIterator->seekTo(start_sample_index);
862            if (err != OK) {
863                return err;
864            }
865            uint32_t sample_time = mSampleIterator->getSampleTime();
866
867            err = mSampleIterator->seekTo(mSyncSamples[left]);
868            if (err != OK) {
869                return err;
870            }
871            uint32_t upper_time = mSampleIterator->getSampleTime();
872
873            err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
874            if (err != OK) {
875                return err;
876            }
877            uint32_t lower_time = mSampleIterator->getSampleTime();
878
879            // use abs_difference for safety
880            if (abs_difference(upper_time, sample_time) >
881                abs_difference(sample_time, lower_time)) {
882                --left;
883            }
884            break;
885        }
886    }
887
888    *sample_index = mSyncSamples[left];
889    return OK;
890}
891
892status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
893    Mutex::Autolock autoLock(mLock);
894
895    if (mSyncSampleOffset < 0) {
896        // All samples are sync-samples.
897        *sample_index = 0;
898        return OK;
899    }
900
901    uint32_t bestSampleIndex = 0;
902    size_t maxSampleSize = 0;
903
904    static const size_t kMaxNumSyncSamplesToScan = 20;
905
906    // Consider the first kMaxNumSyncSamplesToScan sync samples and
907    // pick the one with the largest (compressed) size as the thumbnail.
908
909    size_t numSamplesToScan = mNumSyncSamples;
910    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
911        numSamplesToScan = kMaxNumSyncSamplesToScan;
912    }
913
914    for (size_t i = 0; i < numSamplesToScan; ++i) {
915        uint32_t x = mSyncSamples[i];
916
917        // Now x is a sample index.
918        size_t sampleSize;
919        status_t err = getSampleSize_l(x, &sampleSize);
920        if (err != OK) {
921            return err;
922        }
923
924        if (i == 0 || sampleSize > maxSampleSize) {
925            bestSampleIndex = x;
926            maxSampleSize = sampleSize;
927        }
928    }
929
930    *sample_index = bestSampleIndex;
931
932    return OK;
933}
934
935status_t SampleTable::getSampleSize_l(
936        uint32_t sampleIndex, size_t *sampleSize) {
937    return mSampleIterator->getSampleSizeDirect(
938            sampleIndex, sampleSize);
939}
940
941status_t SampleTable::getMetaDataForSample(
942        uint32_t sampleIndex,
943        off64_t *offset,
944        size_t *size,
945        uint32_t *compositionTime,
946        bool *isSyncSample,
947        uint32_t *sampleDuration) {
948    Mutex::Autolock autoLock(mLock);
949
950    status_t err;
951    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
952        return err;
953    }
954
955    if (offset) {
956        *offset = mSampleIterator->getSampleOffset();
957    }
958
959    if (size) {
960        *size = mSampleIterator->getSampleSize();
961    }
962
963    if (compositionTime) {
964        *compositionTime = mSampleIterator->getSampleTime();
965    }
966
967    if (isSyncSample) {
968        *isSyncSample = false;
969        if (mSyncSampleOffset < 0) {
970            // Every sample is a sync sample.
971            *isSyncSample = true;
972        } else {
973            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
974                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
975                ? mLastSyncSampleIndex : 0;
976
977            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
978                ++i;
979            }
980
981            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
982                *isSyncSample = true;
983            }
984
985            mLastSyncSampleIndex = i;
986        }
987    }
988
989    if (sampleDuration) {
990        *sampleDuration = mSampleIterator->getSampleDuration();
991    }
992
993    return OK;
994}
995
996int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
997    return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
998}
999
1000}  // namespace android
1001