SampleTable.cpp revision 9f753df58a70f20db220af31cb202bbd21b30f36
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 "include/SampleTable.h"
22#include "include/SampleIterator.h"
23
24#include <arpa/inet.h>
25
26#include <media/stagefright/DataSource.h>
27#include <media/stagefright/MediaDebug.h>
28#include <media/stagefright/Utils.h>
29
30namespace android {
31
32// static
33const uint32_t SampleTable::kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
34// static
35const uint32_t SampleTable::kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
36// static
37const uint32_t SampleTable::kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
38// static
39const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
40
41////////////////////////////////////////////////////////////////////////////////
42
43SampleTable::SampleTable(const sp<DataSource> &source)
44    : mDataSource(source),
45      mChunkOffsetOffset(-1),
46      mChunkOffsetType(0),
47      mNumChunkOffsets(0),
48      mSampleToChunkOffset(-1),
49      mNumSampleToChunkOffsets(0),
50      mSampleSizeOffset(-1),
51      mSampleSizeFieldSize(0),
52      mDefaultSampleSize(0),
53      mNumSampleSizes(0),
54      mTimeToSampleCount(0),
55      mTimeToSample(NULL),
56      mSampleTimeEntries(NULL),
57      mCompositionTimeDeltaEntries(NULL),
58      mNumCompositionTimeDeltaEntries(0),
59      mSyncSampleOffset(-1),
60      mNumSyncSamples(0),
61      mSyncSamples(NULL),
62      mLastSyncSampleIndex(0),
63      mSampleToChunkEntries(NULL) {
64    mSampleIterator = new SampleIterator(this);
65}
66
67SampleTable::~SampleTable() {
68    delete[] mSampleToChunkEntries;
69    mSampleToChunkEntries = NULL;
70
71    delete[] mSyncSamples;
72    mSyncSamples = NULL;
73
74    delete[] mCompositionTimeDeltaEntries;
75    mCompositionTimeDeltaEntries = NULL;
76
77    delete[] mSampleTimeEntries;
78    mSampleTimeEntries = NULL;
79
80    delete[] mTimeToSample;
81    mTimeToSample = NULL;
82
83    delete mSampleIterator;
84    mSampleIterator = NULL;
85}
86
87status_t SampleTable::setChunkOffsetParams(
88        uint32_t type, off64_t data_offset, size_t data_size) {
89    if (mChunkOffsetOffset >= 0) {
90        return ERROR_MALFORMED;
91    }
92
93    CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
94
95    mChunkOffsetOffset = data_offset;
96    mChunkOffsetType = type;
97
98    if (data_size < 8) {
99        return ERROR_MALFORMED;
100    }
101
102    uint8_t header[8];
103    if (mDataSource->readAt(
104                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
105        return ERROR_IO;
106    }
107
108    if (U32_AT(header) != 0) {
109        // Expected version = 0, flags = 0.
110        return ERROR_MALFORMED;
111    }
112
113    mNumChunkOffsets = U32_AT(&header[4]);
114
115    if (mChunkOffsetType == kChunkOffsetType32) {
116        if (data_size < 8 + mNumChunkOffsets * 4) {
117            return ERROR_MALFORMED;
118        }
119    } else {
120        if (data_size < 8 + mNumChunkOffsets * 8) {
121            return ERROR_MALFORMED;
122        }
123    }
124
125    return OK;
126}
127
128status_t SampleTable::setSampleToChunkParams(
129        off64_t data_offset, size_t data_size) {
130    if (mSampleToChunkOffset >= 0) {
131        return ERROR_MALFORMED;
132    }
133
134    mSampleToChunkOffset = data_offset;
135
136    if (data_size < 8) {
137        return ERROR_MALFORMED;
138    }
139
140    uint8_t header[8];
141    if (mDataSource->readAt(
142                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
143        return ERROR_IO;
144    }
145
146    if (U32_AT(header) != 0) {
147        // Expected version = 0, flags = 0.
148        return ERROR_MALFORMED;
149    }
150
151    mNumSampleToChunkOffsets = U32_AT(&header[4]);
152
153    if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
154        return ERROR_MALFORMED;
155    }
156
157    mSampleToChunkEntries =
158        new SampleToChunkEntry[mNumSampleToChunkOffsets];
159
160    for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
161        uint8_t buffer[12];
162        if (mDataSource->readAt(
163                    mSampleToChunkOffset + 8 + i * 12, buffer, sizeof(buffer))
164                != (ssize_t)sizeof(buffer)) {
165            return ERROR_IO;
166        }
167
168        CHECK(U32_AT(buffer) >= 1);  // chunk index is 1 based in the spec.
169
170        // We want the chunk index to be 0-based.
171        mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
172        mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
173        mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
174    }
175
176    return OK;
177}
178
179status_t SampleTable::setSampleSizeParams(
180        uint32_t type, off64_t data_offset, size_t data_size) {
181    if (mSampleSizeOffset >= 0) {
182        return ERROR_MALFORMED;
183    }
184
185    CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
186
187    mSampleSizeOffset = data_offset;
188
189    if (data_size < 12) {
190        return ERROR_MALFORMED;
191    }
192
193    uint8_t header[12];
194    if (mDataSource->readAt(
195                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
196        return ERROR_IO;
197    }
198
199    if (U32_AT(header) != 0) {
200        // Expected version = 0, flags = 0.
201        return ERROR_MALFORMED;
202    }
203
204    mDefaultSampleSize = U32_AT(&header[4]);
205    mNumSampleSizes = U32_AT(&header[8]);
206
207    if (type == kSampleSizeType32) {
208        mSampleSizeFieldSize = 32;
209
210        if (mDefaultSampleSize != 0) {
211            return OK;
212        }
213
214        if (data_size < 12 + mNumSampleSizes * 4) {
215            return ERROR_MALFORMED;
216        }
217    } else {
218        if ((mDefaultSampleSize & 0xffffff00) != 0) {
219            // The high 24 bits are reserved and must be 0.
220            return ERROR_MALFORMED;
221        }
222
223        mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
224        mDefaultSampleSize = 0;
225
226        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
227            && mSampleSizeFieldSize != 16) {
228            return ERROR_MALFORMED;
229        }
230
231        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
232            return ERROR_MALFORMED;
233        }
234    }
235
236    return OK;
237}
238
239status_t SampleTable::setTimeToSampleParams(
240        off64_t data_offset, size_t data_size) {
241    if (mTimeToSample != NULL || data_size < 8) {
242        return ERROR_MALFORMED;
243    }
244
245    uint8_t header[8];
246    if (mDataSource->readAt(
247                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
248        return ERROR_IO;
249    }
250
251    if (U32_AT(header) != 0) {
252        // Expected version = 0, flags = 0.
253        return ERROR_MALFORMED;
254    }
255
256    mTimeToSampleCount = U32_AT(&header[4]);
257    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];
258
259    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
260    if (mDataSource->readAt(
261                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
262        return ERROR_IO;
263    }
264
265    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
266        mTimeToSample[i] = ntohl(mTimeToSample[i]);
267    }
268
269    return OK;
270}
271
272status_t SampleTable::setCompositionTimeToSampleParams(
273        off64_t data_offset, size_t data_size) {
274    LOGI("There are reordered frames present.");
275
276    if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
277        return ERROR_MALFORMED;
278    }
279
280    uint8_t header[8];
281    if (mDataSource->readAt(
282                data_offset, header, sizeof(header))
283            < (ssize_t)sizeof(header)) {
284        return ERROR_IO;
285    }
286
287    if (U32_AT(header) != 0) {
288        // Expected version = 0, flags = 0.
289        return ERROR_MALFORMED;
290    }
291
292    size_t numEntries = U32_AT(&header[4]);
293
294    if (data_size != (numEntries + 1) * 8) {
295        return ERROR_MALFORMED;
296    }
297
298    mNumCompositionTimeDeltaEntries = numEntries;
299    mCompositionTimeDeltaEntries = new uint32_t[2 * numEntries];
300
301    if (mDataSource->readAt(
302                data_offset + 8, mCompositionTimeDeltaEntries, numEntries * 8)
303            < (ssize_t)numEntries * 8) {
304        delete[] mCompositionTimeDeltaEntries;
305        mCompositionTimeDeltaEntries = NULL;
306
307        return ERROR_IO;
308    }
309
310    for (size_t i = 0; i < 2 * numEntries; ++i) {
311        mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
312    }
313
314    return OK;
315}
316
317status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
318    if (mSyncSampleOffset >= 0 || data_size < 8) {
319        return ERROR_MALFORMED;
320    }
321
322    mSyncSampleOffset = data_offset;
323
324    uint8_t header[8];
325    if (mDataSource->readAt(
326                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
327        return ERROR_IO;
328    }
329
330    if (U32_AT(header) != 0) {
331        // Expected version = 0, flags = 0.
332        return ERROR_MALFORMED;
333    }
334
335    mNumSyncSamples = U32_AT(&header[4]);
336
337    if (mNumSyncSamples < 2) {
338        LOGV("Table of sync samples is empty or has only a single entry!");
339    }
340
341    mSyncSamples = new uint32_t[mNumSyncSamples];
342    size_t size = mNumSyncSamples * sizeof(uint32_t);
343    if (mDataSource->readAt(mSyncSampleOffset + 8, mSyncSamples, size)
344            != (ssize_t)size) {
345        return ERROR_IO;
346    }
347
348    for (size_t i = 0; i < mNumSyncSamples; ++i) {
349        mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
350    }
351
352    return OK;
353}
354
355uint32_t SampleTable::countChunkOffsets() const {
356    return mNumChunkOffsets;
357}
358
359uint32_t SampleTable::countSamples() const {
360    return mNumSampleSizes;
361}
362
363status_t SampleTable::getMaxSampleSize(size_t *max_size) {
364    Mutex::Autolock autoLock(mLock);
365
366    *max_size = 0;
367
368    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
369        size_t sample_size;
370        status_t err = getSampleSize_l(i, &sample_size);
371
372        if (err != OK) {
373            return err;
374        }
375
376        if (sample_size > *max_size) {
377            *max_size = sample_size;
378        }
379    }
380
381    return OK;
382}
383
384uint32_t abs_difference(uint32_t time1, uint32_t time2) {
385    return time1 > time2 ? time1 - time2 : time2 - time1;
386}
387
388// static
389int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
390    const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
391    const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
392
393    if (a->mCompositionTime < b->mCompositionTime) {
394        return -1;
395    } else if (a->mCompositionTime > b->mCompositionTime) {
396        return 1;
397    }
398
399    return 0;
400}
401
402void SampleTable::buildSampleEntriesTable() {
403    Mutex::Autolock autoLock(mLock);
404
405    if (mSampleTimeEntries != NULL) {
406        return;
407    }
408
409    mSampleTimeEntries = new SampleTimeEntry[mNumSampleSizes];
410
411    uint32_t sampleIndex = 0;
412    uint32_t sampleTime = 0;
413
414    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
415        uint32_t n = mTimeToSample[2 * i];
416        uint32_t delta = mTimeToSample[2 * i + 1];
417
418        for (uint32_t j = 0; j < n; ++j) {
419            CHECK(sampleIndex < mNumSampleSizes);
420
421            mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
422
423            mSampleTimeEntries[sampleIndex].mCompositionTime =
424                sampleTime + getCompositionTimeOffset(sampleIndex);
425
426            ++sampleIndex;
427            sampleTime += delta;
428        }
429    }
430
431    qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
432          CompareIncreasingTime);
433}
434
435status_t SampleTable::findSampleAtTime(
436        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
437    buildSampleEntriesTable();
438
439    uint32_t left = 0;
440    uint32_t right = mNumSampleSizes;
441    while (left < right) {
442        uint32_t center = (left + right) / 2;
443        uint32_t centerTime = mSampleTimeEntries[center].mCompositionTime;
444
445        if (req_time < centerTime) {
446            right = center;
447        } else if (req_time > centerTime) {
448            left = center + 1;
449        } else {
450            left = center;
451            break;
452        }
453    }
454
455    if (left == mNumSampleSizes) {
456        if (flags == kFlagAfter) {
457            return ERROR_OUT_OF_RANGE;
458        }
459
460        --left;
461    }
462
463    uint32_t closestIndex = left;
464
465    switch (flags) {
466        case kFlagBefore:
467        {
468            while (closestIndex > 0
469                    && mSampleTimeEntries[closestIndex].mCompositionTime
470                            > req_time) {
471                --closestIndex;
472            }
473            break;
474        }
475
476        case kFlagAfter:
477        {
478            while (closestIndex + 1 < mNumSampleSizes
479                    && mSampleTimeEntries[closestIndex].mCompositionTime
480                            < req_time) {
481                ++closestIndex;
482            }
483            break;
484        }
485
486        default:
487        {
488            CHECK(flags == kFlagClosest);
489
490            if (closestIndex > 0) {
491                // Check left neighbour and pick closest.
492                uint32_t absdiff1 =
493                    abs_difference(
494                            mSampleTimeEntries[closestIndex].mCompositionTime,
495                            req_time);
496
497                uint32_t absdiff2 =
498                    abs_difference(
499                            mSampleTimeEntries[closestIndex - 1].mCompositionTime,
500                            req_time);
501
502                if (absdiff1 > absdiff2) {
503                    closestIndex = closestIndex - 1;
504                }
505            }
506
507            break;
508        }
509    }
510
511    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
512
513    return OK;
514}
515
516status_t SampleTable::findSyncSampleNear(
517        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
518    Mutex::Autolock autoLock(mLock);
519
520    *sample_index = 0;
521
522    if (mSyncSampleOffset < 0) {
523        // All samples are sync-samples.
524        *sample_index = start_sample_index;
525        return OK;
526    }
527
528    if (mNumSyncSamples == 0) {
529        *sample_index = 0;
530        return OK;
531    }
532
533    uint32_t left = 0;
534    while (left < mNumSyncSamples) {
535        uint32_t x = mSyncSamples[left];
536
537        if (x >= start_sample_index) {
538            break;
539        }
540
541        ++left;
542    }
543    if (left > 0) {
544        --left;
545    }
546
547    uint32_t x;
548    if (mDataSource->readAt(
549                mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
550        return ERROR_IO;
551    }
552
553    x = ntohl(x);
554    --x;
555
556    if (left + 1 < mNumSyncSamples) {
557        uint32_t y = mSyncSamples[left + 1];
558
559        // our sample lies between sync samples x and y.
560
561        status_t err = mSampleIterator->seekTo(start_sample_index);
562        if (err != OK) {
563            return err;
564        }
565
566        uint32_t sample_time = mSampleIterator->getSampleTime();
567
568        err = mSampleIterator->seekTo(x);
569        if (err != OK) {
570            return err;
571        }
572        uint32_t x_time = mSampleIterator->getSampleTime();
573
574        err = mSampleIterator->seekTo(y);
575        if (err != OK) {
576            return err;
577        }
578
579        uint32_t y_time = mSampleIterator->getSampleTime();
580
581        if (abs_difference(x_time, sample_time)
582                > abs_difference(y_time, sample_time)) {
583            // Pick the sync sample closest (timewise) to the start-sample.
584            x = y;
585            ++left;
586        }
587    }
588
589    switch (flags) {
590        case kFlagBefore:
591        {
592            if (x > start_sample_index) {
593                CHECK(left > 0);
594
595                if (mDataSource->readAt(
596                            mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
597                    return ERROR_IO;
598                }
599
600                x = ntohl(x);
601                --x;
602
603                CHECK(x <= start_sample_index);
604            }
605            break;
606        }
607
608        case kFlagAfter:
609        {
610            if (x < start_sample_index) {
611                if (left + 1 >= mNumSyncSamples) {
612                    return ERROR_OUT_OF_RANGE;
613                }
614
615                x = mSyncSamples[left + 1];
616
617                CHECK(x >= start_sample_index);
618            }
619
620            break;
621        }
622
623        default:
624            break;
625    }
626
627    *sample_index = x;
628
629    return OK;
630}
631
632status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
633    Mutex::Autolock autoLock(mLock);
634
635    if (mSyncSampleOffset < 0) {
636        // All samples are sync-samples.
637        *sample_index = 0;
638        return OK;
639    }
640
641    uint32_t bestSampleIndex = 0;
642    size_t maxSampleSize = 0;
643
644    static const size_t kMaxNumSyncSamplesToScan = 20;
645
646    // Consider the first kMaxNumSyncSamplesToScan sync samples and
647    // pick the one with the largest (compressed) size as the thumbnail.
648
649    size_t numSamplesToScan = mNumSyncSamples;
650    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
651        numSamplesToScan = kMaxNumSyncSamplesToScan;
652    }
653
654    for (size_t i = 0; i < numSamplesToScan; ++i) {
655        uint32_t x = mSyncSamples[i];
656
657        // Now x is a sample index.
658        size_t sampleSize;
659        status_t err = getSampleSize_l(x, &sampleSize);
660        if (err != OK) {
661            return err;
662        }
663
664        if (i == 0 || sampleSize > maxSampleSize) {
665            bestSampleIndex = x;
666            maxSampleSize = sampleSize;
667        }
668    }
669
670    *sample_index = bestSampleIndex;
671
672    return OK;
673}
674
675status_t SampleTable::getSampleSize_l(
676        uint32_t sampleIndex, size_t *sampleSize) {
677    return mSampleIterator->getSampleSizeDirect(
678            sampleIndex, sampleSize);
679}
680
681status_t SampleTable::getMetaDataForSample(
682        uint32_t sampleIndex,
683        off64_t *offset,
684        size_t *size,
685        uint32_t *compositionTime,
686        bool *isSyncSample) {
687    Mutex::Autolock autoLock(mLock);
688
689    status_t err;
690    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
691        return err;
692    }
693
694    if (offset) {
695        *offset = mSampleIterator->getSampleOffset();
696    }
697
698    if (size) {
699        *size = mSampleIterator->getSampleSize();
700    }
701
702    if (compositionTime) {
703        *compositionTime = mSampleIterator->getSampleTime();
704    }
705
706    if (isSyncSample) {
707        *isSyncSample = false;
708        if (mSyncSampleOffset < 0) {
709            // Every sample is a sync sample.
710            *isSyncSample = true;
711        } else {
712            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
713                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
714                ? mLastSyncSampleIndex : 0;
715
716            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
717                ++i;
718            }
719
720            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
721                *isSyncSample = true;
722            }
723
724            mLastSyncSampleIndex = i;
725        }
726    }
727
728    return OK;
729}
730
731uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) const {
732    if (mCompositionTimeDeltaEntries == NULL) {
733        return 0;
734    }
735
736    uint32_t curSample = 0;
737    for (size_t i = 0; i < mNumCompositionTimeDeltaEntries; ++i) {
738        uint32_t sampleCount = mCompositionTimeDeltaEntries[2 * i];
739
740        if (sampleIndex < curSample + sampleCount) {
741            uint32_t sampleDelta = mCompositionTimeDeltaEntries[2 * i + 1];
742
743            return sampleDelta;
744        }
745
746        curSample += sampleCount;
747    }
748
749    return 0;
750}
751
752}  // namespace android
753
754