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 "SampleTable.h"
24 #include "SampleIterator.h"
25 
26 #include <arpa/inet.h>
27 
28 #include <media/MediaExtractorPluginApi.h>
29 #include <media/stagefright/foundation/ADebug.h>
30 #include <media/stagefright/foundation/ByteUtils.h>
31 
32 /* TODO: remove after being merged into other branches */
33 #ifndef UINT32_MAX
34 #define UINT32_MAX       (4294967295U)
35 #endif
36 
37 namespace android {
38 
39 // static
40 const uint32_t SampleTable::kChunkOffsetType32 = FOURCC("stco");
41 // static
42 const uint32_t SampleTable::kChunkOffsetType64 = FOURCC("co64");
43 // static
44 const uint32_t SampleTable::kSampleSizeType32 = FOURCC("stsz");
45 // static
46 const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC("stz2");
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 
50 const off64_t kMaxOffset = std::numeric_limits<off64_t>::max();
51 
52 struct 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 
60 private:
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 
CompositionDeltaLookup()72 SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
73     : mDeltaEntries(NULL),
74       mNumDeltaEntries(0),
75       mCurrentDeltaEntry(0),
76       mCurrentEntrySampleIndex(0) {
77 }
78 
setEntries(const int32_t * deltaEntries,size_t numDeltaEntries)79 void 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 
getCompositionTimeOffset(uint32_t sampleIndex)89 int32_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 
SampleTable(DataSourceHelper * source)117 SampleTable::SampleTable(DataSourceHelper *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 
~SampleTable()144 SampleTable::~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 
isValid() const167 bool SampleTable::isValid() const {
168     return mChunkOffsetOffset >= 0
169         && mSampleToChunkOffset >= 0
170         && mSampleSizeOffset >= 0
171         && mHasTimeToSample;
172 }
173 
setChunkOffsetParams(uint32_t type,off64_t data_offset,size_t data_size)174 status_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 
setSampleToChunkParams(off64_t data_offset,size_t data_size)215 status_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 
setSampleSizeParams(uint32_t type,off64_t data_offset,size_t data_size)312 status_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 
setTimeToSampleParams(off64_t data_offset,size_t data_size)376 status_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 > (data_size - 8) / (2 * sizeof(uint32_t))) {
395         ALOGE("Time-to-sample table size too large.");
396         return ERROR_OUT_OF_RANGE;
397     }
398 
399     uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
400     mTotalSize += allocSize;
401     if (mTotalSize > kMaxTotalSize) {
402         ALOGE("Time-to-sample table size would make sample table too large.\n"
403               "    Requested time-to-sample table size = %llu\n"
404               "    Eventual sample table size >= %llu\n"
405               "    Allowed sample table size = %llu\n",
406               (unsigned long long)allocSize,
407               (unsigned long long)mTotalSize,
408               (unsigned long long)kMaxTotalSize);
409         return ERROR_OUT_OF_RANGE;
410     }
411 
412     mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
413     if (!mTimeToSample) {
414         ALOGE("Cannot allocate time-to-sample table with %llu entries.",
415                 (unsigned long long)mTimeToSampleCount);
416         return ERROR_OUT_OF_RANGE;
417     }
418 
419     if (mDataSource->readAt(data_offset + 8, mTimeToSample,
420             (size_t)allocSize) < (ssize_t)allocSize) {
421         ALOGE("Incomplete data read for time-to-sample table.");
422         return ERROR_IO;
423     }
424 
425     for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
426         mTimeToSample[i] = ntohl(mTimeToSample[i]);
427     }
428 
429     mHasTimeToSample = true;
430     return OK;
431 }
432 
433 // NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
434 // contains signed values, however some software creates version 0 files that
435 // contain signed values, so we're always treating the values as signed,
436 // regardless of version.
setCompositionTimeToSampleParams(off64_t data_offset,size_t data_size)437 status_t SampleTable::setCompositionTimeToSampleParams(
438         off64_t data_offset, size_t data_size) {
439     ALOGI("There are reordered frames present.");
440 
441     if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
442         return ERROR_MALFORMED;
443     }
444 
445     uint8_t header[8];
446     if (mDataSource->readAt(
447                 data_offset, header, sizeof(header))
448             < (ssize_t)sizeof(header)) {
449         return ERROR_IO;
450     }
451 
452     uint32_t flags = U32_AT(header);
453     uint32_t version = flags >> 24;
454     flags &= 0xffffff;
455 
456     if ((version != 0 && version != 1) || flags != 0) {
457         // Expected version = 0 or 1, flags = 0.
458         return ERROR_MALFORMED;
459     }
460 
461     size_t numEntries = U32_AT(&header[4]);
462 
463     if (((SIZE_MAX / 8) - 1 < numEntries) || (data_size != (numEntries + 1) * 8)) {
464         return ERROR_MALFORMED;
465     }
466 
467     mNumCompositionTimeDeltaEntries = numEntries;
468     uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
469     if (allocSize > kMaxTotalSize) {
470         ALOGE("Composition-time-to-sample table size too large.");
471         return ERROR_OUT_OF_RANGE;
472     }
473 
474     mTotalSize += allocSize;
475     if (mTotalSize > kMaxTotalSize) {
476         ALOGE("Composition-time-to-sample table would make sample table too large.\n"
477               "    Requested composition-time-to-sample table size = %llu\n"
478               "    Eventual sample table size >= %llu\n"
479               "    Allowed sample table size = %llu\n",
480               (unsigned long long)allocSize,
481               (unsigned long long)mTotalSize,
482               (unsigned long long)kMaxTotalSize);
483         return ERROR_OUT_OF_RANGE;
484     }
485 
486     mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
487     if (!mCompositionTimeDeltaEntries) {
488         ALOGE("Cannot allocate composition-time-to-sample table with %llu "
489                 "entries.", (unsigned long long)numEntries);
490         return ERROR_OUT_OF_RANGE;
491     }
492 
493     if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
494             (size_t)allocSize) < (ssize_t)allocSize) {
495         delete[] mCompositionTimeDeltaEntries;
496         mCompositionTimeDeltaEntries = NULL;
497 
498         return ERROR_IO;
499     }
500 
501     for (size_t i = 0; i < 2 * numEntries; ++i) {
502         mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
503     }
504 
505     mCompositionDeltaLookup->setEntries(
506             mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
507 
508     return OK;
509 }
510 
setSyncSampleParams(off64_t data_offset,size_t data_size)511 status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
512     if (mSyncSampleOffset >= 0 || data_size < 8) {
513         return ERROR_MALFORMED;
514     }
515 
516     uint8_t header[8];
517     if (mDataSource->readAt(
518                 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
519         return ERROR_IO;
520     }
521 
522     if (U32_AT(header) != 0) {
523         // Expected version = 0, flags = 0.
524         return ERROR_MALFORMED;
525     }
526 
527     uint32_t numSyncSamples = U32_AT(&header[4]);
528 
529     if (numSyncSamples < 2) {
530         ALOGV("Table of sync samples is empty or has only a single entry!");
531     }
532 
533     uint64_t allocSize = (uint64_t)numSyncSamples * sizeof(uint32_t);
534     if (allocSize > data_size - 8) {
535         ALOGW("b/124771364 - allocSize(%lu) > size(%lu)",
536                 (unsigned long)allocSize, (unsigned long)(data_size - 8));
537         android_errorWriteLog(0x534e4554, "124771364");
538         return ERROR_MALFORMED;
539     }
540     if (allocSize > kMaxTotalSize) {
541         ALOGE("Sync sample table size too large.");
542         return ERROR_OUT_OF_RANGE;
543     }
544 
545     mTotalSize += allocSize;
546     if (mTotalSize > kMaxTotalSize) {
547         ALOGE("Sync sample table size would make sample table too large.\n"
548               "    Requested sync sample table size = %llu\n"
549               "    Eventual sample table size >= %llu\n"
550               "    Allowed sample table size = %llu\n",
551               (unsigned long long)allocSize,
552               (unsigned long long)mTotalSize,
553               (unsigned long long)kMaxTotalSize);
554         return ERROR_OUT_OF_RANGE;
555     }
556 
557     mSyncSamples = new (std::nothrow) uint32_t[numSyncSamples];
558     if (!mSyncSamples) {
559         ALOGE("Cannot allocate sync sample table with %llu entries.",
560                 (unsigned long long)numSyncSamples);
561         return ERROR_OUT_OF_RANGE;
562     }
563 
564     if (mDataSource->readAt(data_offset + 8, mSyncSamples,
565             (size_t)allocSize) != (ssize_t)allocSize) {
566         delete[] mSyncSamples;
567         mSyncSamples = NULL;
568         return ERROR_IO;
569     }
570 
571     for (size_t i = 0; i < numSyncSamples; ++i) {
572         if (mSyncSamples[i] == 0) {
573             ALOGE("b/32423862, unexpected zero value in stss");
574             continue;
575         }
576         mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
577     }
578 
579     mSyncSampleOffset = data_offset;
580     mNumSyncSamples = numSyncSamples;
581 
582     return OK;
583 }
584 
countChunkOffsets() const585 uint32_t SampleTable::countChunkOffsets() const {
586     return mNumChunkOffsets;
587 }
588 
countSamples() const589 uint32_t SampleTable::countSamples() const {
590     return mNumSampleSizes;
591 }
592 
getMaxSampleSize(size_t * max_size)593 status_t SampleTable::getMaxSampleSize(size_t *max_size) {
594     Mutex::Autolock autoLock(mLock);
595 
596     *max_size = 0;
597 
598     for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
599         size_t sample_size;
600         status_t err = getSampleSize_l(i, &sample_size);
601 
602         if (err != OK) {
603             return err;
604         }
605 
606         if (sample_size > *max_size) {
607             *max_size = sample_size;
608         }
609     }
610 
611     return OK;
612 }
613 
abs_difference(uint64_t time1,uint64_t time2)614 uint32_t abs_difference(uint64_t time1, uint64_t time2) {
615     return time1 > time2 ? time1 - time2 : time2 - time1;
616 }
617 
618 // static
CompareIncreasingTime(const void * _a,const void * _b)619 int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
620     const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
621     const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
622 
623     if (a->mCompositionTime < b->mCompositionTime) {
624         return -1;
625     } else if (a->mCompositionTime > b->mCompositionTime) {
626         return 1;
627     }
628 
629     return 0;
630 }
631 
buildSampleEntriesTable()632 void SampleTable::buildSampleEntriesTable() {
633     Mutex::Autolock autoLock(mLock);
634 
635     if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
636         if (mNumSampleSizes == 0) {
637             ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
638         }
639         return;
640     }
641 
642     mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
643     if (mTotalSize > kMaxTotalSize) {
644         ALOGE("Sample entry table size would make sample table too large.\n"
645               "    Requested sample entry table size = %llu\n"
646               "    Eventual sample table size >= %llu\n"
647               "    Allowed sample table size = %llu\n",
648               (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
649               (unsigned long long)mTotalSize,
650               (unsigned long long)kMaxTotalSize);
651         return;
652     }
653 
654     mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
655 
656     if (!mSampleTimeEntries) {
657         ALOGE("Cannot allocate sample entry table with %llu entries.",
658                 (unsigned long long)mNumSampleSizes);
659         return;
660     }
661     memset(mSampleTimeEntries, 0, sizeof(SampleTimeEntry) * mNumSampleSizes);
662 
663     uint32_t sampleIndex = 0;
664     uint64_t sampleTime = 0;
665 
666     for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
667         uint32_t n = mTimeToSample[2 * i];
668         uint32_t delta = mTimeToSample[2 * i + 1];
669 
670         for (uint32_t j = 0; j < n; ++j) {
671             if (sampleIndex < mNumSampleSizes) {
672                 // Technically this should always be the case if the file
673                 // is well-formed, but you know... there's (gasp) malformed
674                 // content out there.
675 
676                 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
677 
678                 int32_t compTimeDelta =
679                     mCompositionDeltaLookup->getCompositionTimeOffset(
680                             sampleIndex);
681 
682                 if ((compTimeDelta < 0 && sampleTime <
683                         (compTimeDelta == INT32_MIN ?
684                                 INT32_MAX : uint32_t(-compTimeDelta)))
685                         || (compTimeDelta > 0 &&
686                                 sampleTime > UINT64_MAX - compTimeDelta)) {
687                     ALOGE("%llu + %d would overflow, clamping",
688                             (unsigned long long) sampleTime, compTimeDelta);
689                     if (compTimeDelta < 0) {
690                         sampleTime = 0;
691                     } else {
692                         sampleTime = UINT64_MAX;
693                     }
694                     compTimeDelta = 0;
695                 }
696 
697                 mSampleTimeEntries[sampleIndex].mCompositionTime =
698                         compTimeDelta > 0 ? sampleTime + compTimeDelta:
699                                 sampleTime - (-compTimeDelta);
700             }
701 
702             ++sampleIndex;
703             if (sampleTime > UINT64_MAX - delta) {
704                 ALOGE("%llu + %u would overflow, clamping",
705                     (unsigned long long) sampleTime, delta);
706                 sampleTime = UINT64_MAX;
707             } else {
708                 sampleTime += delta;
709             }
710         }
711     }
712 
713     qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
714           CompareIncreasingTime);
715 }
716 
findSampleAtTime(uint64_t req_time,uint64_t scale_num,uint64_t scale_den,uint32_t * sample_index,uint32_t flags)717 status_t SampleTable::findSampleAtTime(
718         uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
719         uint32_t *sample_index, uint32_t flags) {
720     buildSampleEntriesTable();
721 
722     if (mSampleTimeEntries == NULL) {
723         return ERROR_OUT_OF_RANGE;
724     }
725 
726     if (flags == kFlagFrameIndex) {
727         if (req_time >= mNumSampleSizes) {
728             return ERROR_OUT_OF_RANGE;
729         }
730         *sample_index = mSampleTimeEntries[req_time].mSampleIndex;
731         return OK;
732     }
733 
734     uint32_t left = 0;
735     uint32_t right_plus_one = mNumSampleSizes;
736     while (left < right_plus_one) {
737         uint32_t center = left + (right_plus_one - left) / 2;
738         uint64_t centerTime =
739             getSampleTime(center, scale_num, scale_den);
740 
741         if (req_time < centerTime) {
742             right_plus_one = center;
743         } else if (req_time > centerTime) {
744             left = center + 1;
745         } else {
746             *sample_index = mSampleTimeEntries[center].mSampleIndex;
747             return OK;
748         }
749     }
750 
751     uint32_t closestIndex = left;
752 
753     if (closestIndex == mNumSampleSizes) {
754         if (flags == kFlagAfter) {
755             return ERROR_OUT_OF_RANGE;
756         }
757         flags = kFlagBefore;
758     } else if (closestIndex == 0) {
759         if (flags == kFlagBefore) {
760             // normally we should return out of range, but that is
761             // treated as end-of-stream.  instead return first sample
762             //
763             // return ERROR_OUT_OF_RANGE;
764         }
765         flags = kFlagAfter;
766     }
767 
768     switch (flags) {
769         case kFlagBefore:
770         {
771             --closestIndex;
772             break;
773         }
774 
775         case kFlagAfter:
776         {
777             // nothing to do
778             break;
779         }
780 
781         default:
782         {
783             CHECK(flags == kFlagClosest);
784             // pick closest based on timestamp. use abs_difference for safety
785             if (abs_difference(
786                     getSampleTime(closestIndex, scale_num, scale_den), req_time) >
787                 abs_difference(
788                     req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
789                 --closestIndex;
790             }
791             break;
792         }
793     }
794 
795     *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
796     return OK;
797 }
798 
findSyncSampleNear(uint32_t start_sample_index,uint32_t * sample_index,uint32_t flags)799 status_t SampleTable::findSyncSampleNear(
800         uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
801     Mutex::Autolock autoLock(mLock);
802 
803     *sample_index = 0;
804 
805     if (mSyncSampleOffset < 0) {
806         // All samples are sync-samples.
807         *sample_index = start_sample_index;
808         return OK;
809     }
810 
811     if (mNumSyncSamples == 0) {
812         *sample_index = 0;
813         return OK;
814     }
815 
816     uint32_t left = 0;
817     uint32_t right_plus_one = mNumSyncSamples;
818     while (left < right_plus_one) {
819         uint32_t center = left + (right_plus_one - left) / 2;
820         uint32_t x = mSyncSamples[center];
821 
822         if (start_sample_index < x) {
823             right_plus_one = center;
824         } else if (start_sample_index > x) {
825             left = center + 1;
826         } else {
827             *sample_index = x;
828             return OK;
829         }
830     }
831 
832     if (left == mNumSyncSamples) {
833         if (flags == kFlagAfter) {
834             ALOGE("tried to find a sync frame after the last one: %d", left);
835             return ERROR_OUT_OF_RANGE;
836         }
837         flags = kFlagBefore;
838     }
839     else if (left == 0) {
840         if (flags == kFlagBefore) {
841             ALOGE("tried to find a sync frame before the first one: %d", left);
842 
843             // normally we should return out of range, but that is
844             // treated as end-of-stream.  instead seek to first sync
845             //
846             // return ERROR_OUT_OF_RANGE;
847         }
848         flags = kFlagAfter;
849     }
850 
851     // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
852     switch (flags) {
853         case kFlagBefore:
854         {
855             --left;
856             break;
857         }
858         case kFlagAfter:
859         {
860             // nothing to do
861             break;
862         }
863         default:
864         {
865             // this route is not used, but implement it nonetheless
866             CHECK(flags == kFlagClosest);
867 
868             status_t err = mSampleIterator->seekTo(start_sample_index);
869             if (err != OK) {
870                 return err;
871             }
872             uint64_t sample_time = mSampleIterator->getSampleTime();
873 
874             err = mSampleIterator->seekTo(mSyncSamples[left]);
875             if (err != OK) {
876                 return err;
877             }
878             uint64_t upper_time = mSampleIterator->getSampleTime();
879 
880             err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
881             if (err != OK) {
882                 return err;
883             }
884             uint64_t lower_time = mSampleIterator->getSampleTime();
885 
886             // use abs_difference for safety
887             if (abs_difference(upper_time, sample_time) >
888                 abs_difference(sample_time, lower_time)) {
889                 --left;
890             }
891             break;
892         }
893     }
894 
895     *sample_index = mSyncSamples[left];
896     return OK;
897 }
898 
findThumbnailSample(uint32_t * sample_index)899 status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
900     Mutex::Autolock autoLock(mLock);
901 
902     if (mSyncSampleOffset < 0) {
903         // All samples are sync-samples.
904         *sample_index = 0;
905         return OK;
906     }
907 
908     uint32_t bestSampleIndex = 0;
909     size_t maxSampleSize = 0;
910 
911     static const size_t kMaxNumSyncSamplesToScan = 20;
912 
913     // Consider the first kMaxNumSyncSamplesToScan sync samples and
914     // pick the one with the largest (compressed) size as the thumbnail.
915 
916     size_t numSamplesToScan = mNumSyncSamples;
917     if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
918         numSamplesToScan = kMaxNumSyncSamplesToScan;
919     }
920 
921     for (size_t i = 0; i < numSamplesToScan; ++i) {
922         uint32_t x = mSyncSamples[i];
923 
924         // Now x is a sample index.
925         size_t sampleSize;
926         status_t err = getSampleSize_l(x, &sampleSize);
927         if (err != OK) {
928             return err;
929         }
930 
931         if (i == 0 || sampleSize > maxSampleSize) {
932             bestSampleIndex = x;
933             maxSampleSize = sampleSize;
934         }
935     }
936 
937     *sample_index = bestSampleIndex;
938 
939     return OK;
940 }
941 
getSampleSize_l(uint32_t sampleIndex,size_t * sampleSize)942 status_t SampleTable::getSampleSize_l(
943         uint32_t sampleIndex, size_t *sampleSize) {
944     return mSampleIterator->getSampleSizeDirect(
945             sampleIndex, sampleSize);
946 }
947 
getLastSampleIndexInChunk()948 uint32_t SampleTable::getLastSampleIndexInChunk() {
949     Mutex::Autolock autoLock(mLock);
950     return mSampleIterator->getLastSampleIndexInChunk();
951 }
952 
getMetaDataForSample(uint32_t sampleIndex,off64_t * offset,size_t * size,uint64_t * compositionTime,bool * isSyncSample,uint64_t * sampleDuration)953 status_t SampleTable::getMetaDataForSample(
954         uint32_t sampleIndex,
955         off64_t *offset,
956         size_t *size,
957         uint64_t *compositionTime,
958         bool *isSyncSample,
959         uint64_t *sampleDuration) {
960     Mutex::Autolock autoLock(mLock);
961 
962     status_t err;
963     if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
964         return err;
965     }
966 
967     if (offset) {
968         *offset = mSampleIterator->getSampleOffset();
969     }
970 
971     if (size) {
972         *size = mSampleIterator->getSampleSize();
973     }
974 
975     if (compositionTime) {
976         *compositionTime = mSampleIterator->getSampleTime();
977     }
978 
979     if (isSyncSample) {
980         *isSyncSample = false;
981         if (mSyncSampleOffset < 0) {
982             // Every sample is a sync sample.
983             *isSyncSample = true;
984         } else {
985             size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
986                     && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
987                 ? mLastSyncSampleIndex : 0;
988 
989             while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
990                 ++i;
991             }
992 
993             if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
994                 *isSyncSample = true;
995             }
996 
997             mLastSyncSampleIndex = i;
998         }
999     }
1000 
1001     if (sampleDuration) {
1002         *sampleDuration = mSampleIterator->getSampleDuration();
1003     }
1004 
1005     return OK;
1006 }
1007 
getCompositionTimeOffset(uint32_t sampleIndex)1008 int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
1009     return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
1010 }
1011 
1012 }  // namespace android
1013