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