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