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