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