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