SampleTable.cpp revision e46b7be812d68e49710b34048662cbf18e2a6550
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#include <utils/Log.h>
19
20#include <arpa/inet.h>
21#include <assert.h>
22
23#include <media/stagefright/DataSource.h>
24#include <media/stagefright/SampleTable.h>
25#include <media/stagefright/Utils.h>
26
27namespace android {
28
29static const uint32_t kChunkOffsetType32 = FOURCC('s', 't', 'c', 'o');
30static const uint32_t kChunkOffsetType64 = FOURCC('c', 'o', '6', '4');
31static const uint32_t kSampleSizeType32 = FOURCC('s', 't', 's', 'z');
32static const uint32_t kSampleSizeTypeCompact = FOURCC('s', 't', 'z', '2');
33
34SampleTable::SampleTable(DataSource *source)
35    : mDataSource(source),
36      mChunkOffsetOffset(-1),
37      mChunkOffsetType(0),
38      mNumChunkOffsets(0),
39      mSampleToChunkOffset(-1),
40      mNumSampleToChunkOffsets(0),
41      mSampleSizeOffset(-1),
42      mSampleSizeFieldSize(0),
43      mDefaultSampleSize(0),
44      mNumSampleSizes(0),
45      mTimeToSampleCount(0),
46      mTimeToSample(NULL),
47      mSyncSampleOffset(-1),
48      mNumSyncSamples(0) {
49}
50
51SampleTable::~SampleTable() {
52    delete[] mTimeToSample;
53    mTimeToSample = NULL;
54}
55
56status_t SampleTable::setChunkOffsetParams(
57        uint32_t type, off_t data_offset, off_t data_size) {
58    if (mChunkOffsetOffset >= 0) {
59        return ERROR_MALFORMED;
60    }
61
62    assert(type == kChunkOffsetType32 || type == kChunkOffsetType64);
63
64    mChunkOffsetOffset = data_offset;
65    mChunkOffsetType = type;
66
67    if (data_size < 8) {
68        return ERROR_MALFORMED;
69    }
70
71    uint8_t header[8];
72    if (mDataSource->read_at(
73                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
74        return ERROR_IO;
75    }
76
77    if (U32_AT(header) != 0) {
78        // Expected version = 0, flags = 0.
79        return ERROR_MALFORMED;
80    }
81
82    mNumChunkOffsets = U32_AT(&header[4]);
83
84    if (mChunkOffsetType == kChunkOffsetType32) {
85        if (data_size < 8 + mNumChunkOffsets * 4) {
86            return ERROR_MALFORMED;
87        }
88    } else {
89        if (data_size < 8 + mNumChunkOffsets * 8) {
90            return ERROR_MALFORMED;
91        }
92    }
93
94    return OK;
95}
96
97status_t SampleTable::setSampleToChunkParams(
98        off_t data_offset, off_t data_size) {
99    if (mSampleToChunkOffset >= 0) {
100        return ERROR_MALFORMED;
101    }
102
103    mSampleToChunkOffset = data_offset;
104
105    if (data_size < 8) {
106        return ERROR_MALFORMED;
107    }
108
109    uint8_t header[8];
110    if (mDataSource->read_at(
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    mNumSampleToChunkOffsets = U32_AT(&header[4]);
121
122    if (data_size < 8 + mNumSampleToChunkOffsets * 12) {
123        return ERROR_MALFORMED;
124    }
125
126    return OK;
127}
128
129status_t SampleTable::setSampleSizeParams(
130        uint32_t type, off_t data_offset, off_t data_size) {
131    if (mSampleSizeOffset >= 0) {
132        return ERROR_MALFORMED;
133    }
134
135    assert(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
136
137    mSampleSizeOffset = data_offset;
138
139    if (data_size < 12) {
140        return ERROR_MALFORMED;
141    }
142
143    uint8_t header[12];
144    if (mDataSource->read_at(
145                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
146        return ERROR_IO;
147    }
148
149    if (U32_AT(header) != 0) {
150        // Expected version = 0, flags = 0.
151        return ERROR_MALFORMED;
152    }
153
154    mDefaultSampleSize = U32_AT(&header[4]);
155    mNumSampleSizes = U32_AT(&header[8]);
156
157    if (type == kSampleSizeType32) {
158        mSampleSizeFieldSize = 32;
159
160        if (mDefaultSampleSize != 0) {
161            return OK;
162        }
163
164        if (data_size < 12 + mNumSampleSizes * 4) {
165            return ERROR_MALFORMED;
166        }
167    } else {
168        if ((mDefaultSampleSize & 0xffffff00) != 0) {
169            // The high 24 bits are reserved and must be 0.
170            return ERROR_MALFORMED;
171        }
172
173        mSampleSizeFieldSize = mDefaultSampleSize & 0xf;
174        mDefaultSampleSize = 0;
175
176        if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
177            && mSampleSizeFieldSize != 16) {
178            return ERROR_MALFORMED;
179        }
180
181        if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
182            return ERROR_MALFORMED;
183        }
184    }
185
186    return OK;
187}
188
189status_t SampleTable::setTimeToSampleParams(
190        off_t data_offset, off_t data_size) {
191    if (mTimeToSample != NULL || data_size < 8) {
192        return ERROR_MALFORMED;
193    }
194
195    uint8_t header[8];
196    if (mDataSource->read_at(
197                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
198        return ERROR_IO;
199    }
200
201    if (U32_AT(header) != 0) {
202        // Expected version = 0, flags = 0.
203        return ERROR_MALFORMED;
204    }
205
206    mTimeToSampleCount = U32_AT(&header[4]);
207    mTimeToSample = new uint32_t[mTimeToSampleCount * 2];
208
209    size_t size = sizeof(uint32_t) * mTimeToSampleCount * 2;
210    if (mDataSource->read_at(
211                data_offset + 8, mTimeToSample, size) < (ssize_t)size) {
212        return ERROR_IO;
213    }
214
215    for (uint32_t i = 0; i < mTimeToSampleCount * 2; ++i) {
216        mTimeToSample[i] = ntohl(mTimeToSample[i]);
217    }
218
219    return OK;
220}
221
222status_t SampleTable::setSyncSampleParams(off_t data_offset, off_t data_size) {
223    if (mSyncSampleOffset >= 0 || data_size < 8) {
224        return ERROR_MALFORMED;
225    }
226
227    mSyncSampleOffset = data_offset;
228
229    uint8_t header[8];
230    if (mDataSource->read_at(
231                data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
232        return ERROR_IO;
233    }
234
235    if (U32_AT(header) != 0) {
236        // Expected version = 0, flags = 0.
237        return ERROR_MALFORMED;
238    }
239
240    mNumSyncSamples = U32_AT(&header[4]);
241
242    if (mNumSyncSamples < 2) {
243        LOGW("Table of sync samples is empty or has only a single entry!");
244    }
245    return OK;
246}
247
248uint32_t SampleTable::countChunkOffsets() const {
249    return mNumChunkOffsets;
250}
251
252status_t SampleTable::getChunkOffset(uint32_t chunk_index, off_t *offset) {
253    *offset = 0;
254
255    if (mChunkOffsetOffset < 0) {
256        return ERROR_MALFORMED;
257    }
258
259    if (chunk_index >= mNumChunkOffsets) {
260        return ERROR_OUT_OF_RANGE;
261    }
262
263    if (mChunkOffsetType == kChunkOffsetType32) {
264        uint32_t offset32;
265
266        if (mDataSource->read_at(
267                    mChunkOffsetOffset + 8 + 4 * chunk_index,
268                    &offset32,
269                    sizeof(offset32)) < (ssize_t)sizeof(offset32)) {
270            return ERROR_IO;
271        }
272
273        *offset = ntohl(offset32);
274    } else {
275        assert(mChunkOffsetOffset == kChunkOffsetType64);
276
277        uint64_t offset64;
278        if (mDataSource->read_at(
279                    mChunkOffsetOffset + 8 + 8 * chunk_index,
280                    &offset64,
281                    sizeof(offset64)) < (ssize_t)sizeof(offset64)) {
282            return ERROR_IO;
283        }
284
285        *offset = ntoh64(offset64);
286    }
287
288    return OK;
289}
290
291status_t SampleTable::getChunkForSample(
292        uint32_t sample_index,
293        uint32_t *chunk_index,
294        uint32_t *chunk_relative_sample_index,
295        uint32_t *desc_index) {
296    *chunk_index = 0;
297    *chunk_relative_sample_index = 0;
298    *desc_index = 0;
299
300    if (mSampleToChunkOffset < 0) {
301        return ERROR_MALFORMED;
302    }
303
304    if (sample_index >= countSamples()) {
305        return ERROR_END_OF_STREAM;
306    }
307
308    uint32_t first_chunk = 0;
309    uint32_t samples_per_chunk = 0;
310    uint32_t chunk_desc_index = 0;
311
312    uint32_t index = 0;
313    while (index < mNumSampleToChunkOffsets) {
314        uint8_t buffer[12];
315        if (mDataSource->read_at(mSampleToChunkOffset + 8 + index * 12,
316                                 buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
317            return ERROR_IO;
318        }
319
320        uint32_t stop_chunk = U32_AT(buffer);
321        if (sample_index < (stop_chunk - first_chunk) * samples_per_chunk) {
322            break;
323        }
324
325        sample_index -= (stop_chunk - first_chunk) * samples_per_chunk;
326        first_chunk = stop_chunk;
327        samples_per_chunk = U32_AT(&buffer[4]);
328        chunk_desc_index = U32_AT(&buffer[8]);
329
330        ++index;
331    }
332
333    *chunk_index = sample_index / samples_per_chunk + first_chunk - 1;
334    *chunk_relative_sample_index = sample_index % samples_per_chunk;
335    *desc_index = chunk_desc_index;
336
337    return OK;
338}
339
340uint32_t SampleTable::countSamples() const {
341    return mNumSampleSizes;
342}
343
344status_t SampleTable::getSampleSize(
345        uint32_t sample_index, size_t *sample_size) {
346    *sample_size = 0;
347
348    if (mSampleSizeOffset < 0) {
349        return ERROR_MALFORMED;
350    }
351
352    if (sample_index >= mNumSampleSizes) {
353        return ERROR_OUT_OF_RANGE;
354    }
355
356    if (mDefaultSampleSize > 0) {
357        *sample_size = mDefaultSampleSize;
358        return OK;
359    }
360
361    switch (mSampleSizeFieldSize) {
362        case 32:
363        {
364            if (mDataSource->read_at(
365                        mSampleSizeOffset + 12 + 4 * sample_index,
366                        sample_size, sizeof(*sample_size)) < (ssize_t)sizeof(*sample_size)) {
367                return ERROR_IO;
368            }
369
370            *sample_size = ntohl(*sample_size);
371            break;
372        }
373
374        case 16:
375        {
376            uint16_t x;
377            if (mDataSource->read_at(
378                        mSampleSizeOffset + 12 + 2 * sample_index,
379                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
380                return ERROR_IO;
381            }
382
383            *sample_size = ntohs(x);
384            break;
385        }
386
387        case 8:
388        {
389            uint8_t x;
390            if (mDataSource->read_at(
391                        mSampleSizeOffset + 12 + sample_index,
392                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
393                return ERROR_IO;
394            }
395
396            *sample_size = x;
397            break;
398        }
399
400        default:
401        {
402            assert(mSampleSizeFieldSize == 4);
403
404            uint8_t x;
405            if (mDataSource->read_at(
406                        mSampleSizeOffset + 12 + sample_index / 2,
407                        &x, sizeof(x)) < (ssize_t)sizeof(x)) {
408                return ERROR_IO;
409            }
410
411            *sample_size = (sample_index & 1) ? x & 0x0f : x >> 4;
412            break;
413        }
414    }
415
416    return OK;
417}
418
419status_t SampleTable::getSampleOffsetAndSize(
420        uint32_t sample_index, off_t *offset, size_t *size) {
421    Mutex::Autolock autoLock(mLock);
422
423    *offset = 0;
424    *size = 0;
425
426    uint32_t chunk_index;
427    uint32_t chunk_relative_sample_index;
428    uint32_t desc_index;
429    status_t err = getChunkForSample(
430            sample_index, &chunk_index, &chunk_relative_sample_index,
431            &desc_index);
432
433    if (err != OK) {
434        return err;
435    }
436
437    err = getChunkOffset(chunk_index, offset);
438
439    if (err != OK) {
440        return err;
441    }
442
443    for (uint32_t j = 0; j < chunk_relative_sample_index; ++j) {
444        size_t sample_size;
445        err = getSampleSize(sample_index - j - 1, &sample_size);
446
447        if (err != OK) {
448            return err;
449        }
450
451        *offset += sample_size;
452    }
453
454    err = getSampleSize(sample_index, size);
455
456    if (err != OK) {
457        return err;
458    }
459
460    return OK;
461}
462
463status_t SampleTable::getMaxSampleSize(size_t *max_size) {
464    Mutex::Autolock autoLock(mLock);
465
466    *max_size = 0;
467
468    for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
469        size_t sample_size;
470        status_t err = getSampleSize(i, &sample_size);
471
472        if (err != OK) {
473            return err;
474        }
475
476        if (sample_size > *max_size) {
477            *max_size = sample_size;
478        }
479    }
480
481    return OK;
482}
483
484status_t SampleTable::getDecodingTime(uint32_t sample_index, uint32_t *time) {
485    // XXX FIXME idiotic (for the common use-case) O(n) algorithm below...
486
487    Mutex::Autolock autoLock(mLock);
488
489    if (sample_index >= mNumSampleSizes) {
490        return ERROR_OUT_OF_RANGE;
491    }
492
493    uint32_t cur_sample = 0;
494    *time = 0;
495    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
496        uint32_t n = mTimeToSample[2 * i];
497        uint32_t delta = mTimeToSample[2 * i + 1];
498
499        if (sample_index < cur_sample + n) {
500            *time += delta * (sample_index - cur_sample);
501
502            return OK;
503        }
504
505        *time += delta * n;
506        cur_sample += n;
507    }
508
509    return ERROR_OUT_OF_RANGE;
510}
511
512status_t SampleTable::findClosestSample(
513        uint32_t req_time, uint32_t *sample_index, uint32_t flags) {
514    Mutex::Autolock autoLock(mLock);
515
516    uint32_t cur_sample = 0;
517    uint32_t time = 0;
518    for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
519        uint32_t n = mTimeToSample[2 * i];
520        uint32_t delta = mTimeToSample[2 * i + 1];
521
522        if (req_time < time + n * delta) {
523            int j = (req_time - time) / delta;
524
525            *sample_index = cur_sample + j;
526
527            if (flags & kSyncSample_Flag) {
528                return findClosestSyncSample(*sample_index, sample_index);
529            }
530
531            return OK;
532        }
533
534        time += delta * n;
535        cur_sample += n;
536    }
537
538    return ERROR_OUT_OF_RANGE;
539}
540
541status_t SampleTable::findClosestSyncSample(
542        uint32_t start_sample_index, uint32_t *sample_index) {
543    *sample_index = 0;
544
545    if (mSyncSampleOffset < 0) {
546        // All samples are sync-samples.
547        *sample_index = start_sample_index;
548        return OK;
549    }
550
551    uint32_t x;
552    uint32_t left = 0;
553    uint32_t right = mNumSyncSamples;
554    while (left < right) {
555        uint32_t mid = (left + right) / 2;
556        if (mDataSource->read_at(
557                    mSyncSampleOffset + 8 + (mid - 1) * 4, &x, 4) != 4) {
558            return ERROR_IO;
559        }
560
561        x = ntohl(x);
562
563        if (x < (start_sample_index + 1)) {
564            left = mid + 1;
565        } else if (x > (start_sample_index + 1)) {
566            right = mid;
567        } else {
568            break;
569        }
570    }
571
572#if 1
573    // Make sure we return a sample at or _after_ the requested one.
574    // Seeking to a particular time in a media source containing audio and
575    // video will most likely be able to sync fairly close to the requested
576    // time in the audio track but may only be able to seek a fair distance
577    // from the requested time in the video track.
578    // If we seek the video track to a time earlier than the audio track,
579    // we'll cause the video track to be late for quite a while, the decoder
580    // trying to catch up.
581    // If we seek the video track to a time later than the audio track,
582    // audio will start playing fine while no video will be output for a
583    // while, the video decoder will not stress the system.
584    if (mDataSource->read_at(
585                mSyncSampleOffset + 8 + (left - 1) * 4, &x, 4) != 4) {
586        return ERROR_IO;
587    }
588    x = ntohl(x);
589    assert((x - 1) >= start_sample_index);
590#endif
591
592    *sample_index = x - 1;
593
594    return OK;
595}
596
597}  // namespace android
598
599