SampleTable.cpp revision 4678a6dc5f09008481524949a9667af5a6190374
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 & 0xf;
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        --left;
457    }
458
459    uint32_t closestIndex = left;
460
461    switch (flags) {
462        case kFlagBefore:
463        {
464            while (closestIndex > 0
465                    && mSampleTimeEntries[closestIndex].mCompositionTime
466                            > req_time) {
467                --closestIndex;
468            }
469            break;
470        }
471
472        case kFlagAfter:
473        {
474            while (closestIndex + 1 < mNumSampleSizes
475                    && mSampleTimeEntries[closestIndex].mCompositionTime
476                            < req_time) {
477                ++closestIndex;
478            }
479            break;
480        }
481
482        default:
483        {
484            CHECK(flags == kFlagClosest);
485
486            if (closestIndex > 0) {
487                // Check left neighbour and pick closest.
488                uint32_t absdiff1 =
489                    abs_difference(
490                            mSampleTimeEntries[closestIndex].mCompositionTime,
491                            req_time);
492
493                uint32_t absdiff2 =
494                    abs_difference(
495                            mSampleTimeEntries[closestIndex - 1].mCompositionTime,
496                            req_time);
497
498                if (absdiff1 > absdiff2) {
499                    closestIndex = closestIndex - 1;
500                }
501            }
502
503            break;
504        }
505    }
506
507    *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
508
509    return OK;
510}
511
512status_t SampleTable::findSyncSampleNear(
513        uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
514    Mutex::Autolock autoLock(mLock);
515
516    *sample_index = 0;
517
518    if (mSyncSampleOffset < 0) {
519        // All samples are sync-samples.
520        *sample_index = start_sample_index;
521        return OK;
522    }
523
524    if (mNumSyncSamples == 0) {
525        *sample_index = 0;
526        return OK;
527    }
528
529    uint32_t left = 0;
530    while (left < mNumSyncSamples) {
531        uint32_t x = mSyncSamples[left];
532
533        if (x >= start_sample_index) {
534            break;
535        }
536
537        ++left;
538    }
539    if (left > 0) {
540        --left;
541    }
542
543    uint32_t x;
544    if (mDataSource->readAt(
545                mSyncSampleOffset + 8 + left * 4, &x, 4) != 4) {
546        return ERROR_IO;
547    }
548
549    x = ntohl(x);
550    --x;
551
552    if (left + 1 < mNumSyncSamples) {
553        uint32_t y = mSyncSamples[left + 1];
554
555        // our sample lies between sync samples x and y.
556
557        status_t err = mSampleIterator->seekTo(start_sample_index);
558        if (err != OK) {
559            return err;
560        }
561
562        uint32_t sample_time = mSampleIterator->getSampleTime();
563
564        err = mSampleIterator->seekTo(x);
565        if (err != OK) {
566            return err;
567        }
568        uint32_t x_time = mSampleIterator->getSampleTime();
569
570        err = mSampleIterator->seekTo(y);
571        if (err != OK) {
572            return err;
573        }
574
575        uint32_t y_time = mSampleIterator->getSampleTime();
576
577        if (abs_difference(x_time, sample_time)
578                > abs_difference(y_time, sample_time)) {
579            // Pick the sync sample closest (timewise) to the start-sample.
580            x = y;
581            ++left;
582        }
583    }
584
585    switch (flags) {
586        case kFlagBefore:
587        {
588            if (x > start_sample_index) {
589                CHECK(left > 0);
590
591                if (mDataSource->readAt(
592                            mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
593                    return ERROR_IO;
594                }
595
596                x = ntohl(x);
597                --x;
598
599                CHECK(x <= start_sample_index);
600            }
601            break;
602        }
603
604        case kFlagAfter:
605        {
606            if (x < start_sample_index) {
607                if (left + 1 >= mNumSyncSamples) {
608                    return ERROR_OUT_OF_RANGE;
609                }
610
611                x = mSyncSamples[left + 1];
612
613                CHECK(x >= start_sample_index);
614            }
615
616            break;
617        }
618
619        default:
620            break;
621    }
622
623    *sample_index = x;
624
625    return OK;
626}
627
628status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
629    Mutex::Autolock autoLock(mLock);
630
631    if (mSyncSampleOffset < 0) {
632        // All samples are sync-samples.
633        *sample_index = 0;
634        return OK;
635    }
636
637    uint32_t bestSampleIndex = 0;
638    size_t maxSampleSize = 0;
639
640    static const size_t kMaxNumSyncSamplesToScan = 20;
641
642    // Consider the first kMaxNumSyncSamplesToScan sync samples and
643    // pick the one with the largest (compressed) size as the thumbnail.
644
645    size_t numSamplesToScan = mNumSyncSamples;
646    if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
647        numSamplesToScan = kMaxNumSyncSamplesToScan;
648    }
649
650    for (size_t i = 0; i < numSamplesToScan; ++i) {
651        uint32_t x = mSyncSamples[i];
652
653        // Now x is a sample index.
654        size_t sampleSize;
655        status_t err = getSampleSize_l(x, &sampleSize);
656        if (err != OK) {
657            return err;
658        }
659
660        if (i == 0 || sampleSize > maxSampleSize) {
661            bestSampleIndex = x;
662            maxSampleSize = sampleSize;
663        }
664    }
665
666    *sample_index = bestSampleIndex;
667
668    return OK;
669}
670
671status_t SampleTable::getSampleSize_l(
672        uint32_t sampleIndex, size_t *sampleSize) {
673    return mSampleIterator->getSampleSizeDirect(
674            sampleIndex, sampleSize);
675}
676
677status_t SampleTable::getMetaDataForSample(
678        uint32_t sampleIndex,
679        off64_t *offset,
680        size_t *size,
681        uint32_t *compositionTime,
682        bool *isSyncSample) {
683    Mutex::Autolock autoLock(mLock);
684
685    status_t err;
686    if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
687        return err;
688    }
689
690    if (offset) {
691        *offset = mSampleIterator->getSampleOffset();
692    }
693
694    if (size) {
695        *size = mSampleIterator->getSampleSize();
696    }
697
698    if (compositionTime) {
699        *compositionTime = mSampleIterator->getSampleTime();
700    }
701
702    if (isSyncSample) {
703        *isSyncSample = false;
704        if (mSyncSampleOffset < 0) {
705            // Every sample is a sync sample.
706            *isSyncSample = true;
707        } else {
708            size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
709                    && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
710                ? mLastSyncSampleIndex : 0;
711
712            while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
713                ++i;
714            }
715
716            if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
717                *isSyncSample = true;
718            }
719
720            mLastSyncSampleIndex = i;
721        }
722    }
723
724    return OK;
725}
726
727uint32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) const {
728    if (mCompositionTimeDeltaEntries == NULL) {
729        return 0;
730    }
731
732    uint32_t curSample = 0;
733    for (size_t i = 0; i < mNumCompositionTimeDeltaEntries; ++i) {
734        uint32_t sampleCount = mCompositionTimeDeltaEntries[2 * i];
735
736        if (sampleIndex < curSample + sampleCount) {
737            uint32_t sampleDelta = mCompositionTimeDeltaEntries[2 * i + 1];
738
739            return sampleDelta;
740        }
741
742        curSample += sampleCount;
743    }
744
745    return 0;
746}
747
748}  // namespace android
749
750