• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 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 "SampleIterator"
18 //#define LOG_NDEBUG 0
19 #include <utils/Log.h>
20 
21 #include "SampleIterator.h"
22 
23 #include <arpa/inet.h>
24 
25 #include <media/DataSourceBase.h>
26 #include <media/stagefright/foundation/ADebug.h>
27 #include <media/stagefright/foundation/ByteUtils.h>
28 
29 #include "SampleTable.h"
30 
31 namespace android {
32 
SampleIterator(SampleTable * table)33 SampleIterator::SampleIterator(SampleTable *table)
34     : mTable(table),
35       mInitialized(false),
36       mTimeToSampleIndex(0),
37       mTTSSampleIndex(0),
38       mTTSSampleTime(0),
39       mTTSCount(0),
40       mTTSDuration(0) {
41     reset();
42 }
43 
reset()44 void SampleIterator::reset() {
45     mSampleToChunkIndex = 0;
46     mFirstChunk = 0;
47     mFirstChunkSampleIndex = 0;
48     mStopChunk = 0;
49     mStopChunkSampleIndex = 0;
50     mSamplesPerChunk = 0;
51     mChunkDesc = 0;
52 }
53 
seekTo(uint32_t sampleIndex)54 status_t SampleIterator::seekTo(uint32_t sampleIndex) {
55     ALOGV("seekTo(%d)", sampleIndex);
56 
57     if (sampleIndex >= mTable->mNumSampleSizes) {
58         return ERROR_END_OF_STREAM;
59     }
60 
61     if (mTable->mSampleToChunkOffset < 0
62             || mTable->mChunkOffsetOffset < 0
63             || mTable->mSampleSizeOffset < 0
64             || mTable->mTimeToSampleCount == 0) {
65 
66         return ERROR_MALFORMED;
67     }
68 
69     if (mInitialized && mCurrentSampleIndex == sampleIndex) {
70         return OK;
71     }
72 
73     if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) {
74         reset();
75     }
76 
77     if (sampleIndex >= mStopChunkSampleIndex) {
78         status_t err;
79         if ((err = findChunkRange(sampleIndex)) != OK) {
80             ALOGE("findChunkRange failed");
81             return err;
82         }
83     }
84 
85     CHECK(sampleIndex < mStopChunkSampleIndex);
86 
87     if (mSamplesPerChunk == 0) {
88         ALOGE("b/22802344");
89         return ERROR_MALFORMED;
90     }
91 
92     uint32_t chunk =
93         (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk
94         + mFirstChunk;
95 
96     if (!mInitialized || chunk != mCurrentChunkIndex) {
97         status_t err;
98         if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) {
99             ALOGE("getChunkOffset return error");
100             return err;
101         }
102 
103         mCurrentChunkSampleSizes.clear();
104 
105         uint32_t firstChunkSampleIndex =
106             mFirstChunkSampleIndex
107                 + mSamplesPerChunk * (chunk - mFirstChunk);
108 
109         for (uint32_t i = 0; i < mSamplesPerChunk; ++i) {
110             size_t sampleSize;
111             if ((err = getSampleSizeDirect(
112                             firstChunkSampleIndex + i, &sampleSize)) != OK) {
113                 ALOGE("getSampleSizeDirect return error");
114                 // stsc sample count is not sync with stsz sample count
115                 if (err == ERROR_OUT_OF_RANGE) {
116                     ALOGW("stsc samples(%d) not sync with stsz samples(%d)", mSamplesPerChunk, i);
117                     mSamplesPerChunk = i;
118                     break;
119                 } else{
120                     mCurrentChunkSampleSizes.clear();
121                     return err;
122                 }
123             }
124 
125             mCurrentChunkSampleSizes.push(sampleSize);
126         }
127 
128         mCurrentChunkIndex = chunk;
129     }
130 
131     uint32_t chunkRelativeSampleIndex =
132         (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk;
133 
134     mCurrentSampleOffset = mCurrentChunkOffset;
135     for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) {
136         mCurrentSampleOffset += mCurrentChunkSampleSizes[i];
137     }
138 
139     mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex];
140     if (sampleIndex < mTTSSampleIndex) {
141         mTimeToSampleIndex = 0;
142         mTTSSampleIndex = 0;
143         mTTSSampleTime = 0;
144         mTTSCount = 0;
145         mTTSDuration = 0;
146     }
147 
148     status_t err;
149     if ((err = findSampleTimeAndDuration(
150             sampleIndex, &mCurrentSampleTime, &mCurrentSampleDuration)) != OK) {
151         ALOGE("findSampleTime return error");
152         return err;
153     }
154 
155     mCurrentSampleIndex = sampleIndex;
156 
157     mInitialized = true;
158 
159     return OK;
160 }
161 
findChunkRange(uint32_t sampleIndex)162 status_t SampleIterator::findChunkRange(uint32_t sampleIndex) {
163     CHECK(sampleIndex >= mFirstChunkSampleIndex);
164 
165     while (sampleIndex >= mStopChunkSampleIndex) {
166         if (mSampleToChunkIndex == mTable->mNumSampleToChunkOffsets) {
167             return ERROR_OUT_OF_RANGE;
168         }
169 
170         mFirstChunkSampleIndex = mStopChunkSampleIndex;
171 
172         const SampleTable::SampleToChunkEntry *entry =
173             &mTable->mSampleToChunkEntries[mSampleToChunkIndex];
174 
175         mFirstChunk = entry->startChunk;
176         mSamplesPerChunk = entry->samplesPerChunk;
177         mChunkDesc = entry->chunkDesc;
178 
179         if (mSampleToChunkIndex + 1 < mTable->mNumSampleToChunkOffsets) {
180             mStopChunk = entry[1].startChunk;
181 
182             if (mSamplesPerChunk == 0 || mStopChunk < mFirstChunk ||
183                 (mStopChunk - mFirstChunk) > UINT32_MAX / mSamplesPerChunk ||
184                 ((mStopChunk - mFirstChunk) * mSamplesPerChunk >
185                  UINT32_MAX - mFirstChunkSampleIndex)) {
186 
187                 return ERROR_OUT_OF_RANGE;
188             }
189             mStopChunkSampleIndex =
190                 mFirstChunkSampleIndex
191                     + (mStopChunk - mFirstChunk) * mSamplesPerChunk;
192         } else {
193             mStopChunk = 0xffffffff;
194             mStopChunkSampleIndex = 0xffffffff;
195         }
196 
197         ++mSampleToChunkIndex;
198     }
199 
200     return OK;
201 }
202 
getChunkOffset(uint32_t chunk,off64_t * offset)203 status_t SampleIterator::getChunkOffset(uint32_t chunk, off64_t *offset) {
204     *offset = 0;
205 
206     if (chunk >= mTable->mNumChunkOffsets) {
207         return ERROR_OUT_OF_RANGE;
208     }
209 
210     if (mTable->mChunkOffsetType == SampleTable::kChunkOffsetType32) {
211         uint32_t offset32;
212 
213         if (mTable->mDataSource->readAt(
214                     mTable->mChunkOffsetOffset + 8 + 4 * chunk,
215                     &offset32,
216                     sizeof(offset32)) < (ssize_t)sizeof(offset32)) {
217             return ERROR_IO;
218         }
219 
220         *offset = ntohl(offset32);
221     } else {
222         CHECK_EQ(mTable->mChunkOffsetType, SampleTable::kChunkOffsetType64);
223 
224         uint64_t offset64;
225         if (mTable->mDataSource->readAt(
226                     mTable->mChunkOffsetOffset + 8 + 8 * chunk,
227                     &offset64,
228                     sizeof(offset64)) < (ssize_t)sizeof(offset64)) {
229             return ERROR_IO;
230         }
231 
232         *offset = ntoh64(offset64);
233     }
234 
235     return OK;
236 }
237 
getSampleSizeDirect(uint32_t sampleIndex,size_t * size)238 status_t SampleIterator::getSampleSizeDirect(
239         uint32_t sampleIndex, size_t *size) {
240     *size = 0;
241 
242     if (sampleIndex >= mTable->mNumSampleSizes) {
243         return ERROR_OUT_OF_RANGE;
244     }
245 
246     if (mTable->mDefaultSampleSize > 0) {
247         *size = mTable->mDefaultSampleSize;
248         return OK;
249     }
250 
251     switch (mTable->mSampleSizeFieldSize) {
252         case 32:
253         {
254             uint32_t x;
255             if (mTable->mDataSource->readAt(
256                         mTable->mSampleSizeOffset + 12 + 4 * sampleIndex,
257                         &x, sizeof(x)) < (ssize_t)sizeof(x)) {
258                 return ERROR_IO;
259             }
260 
261             *size = ntohl(x);
262             break;
263         }
264 
265         case 16:
266         {
267             uint16_t x;
268             if (mTable->mDataSource->readAt(
269                         mTable->mSampleSizeOffset + 12 + 2 * sampleIndex,
270                         &x, sizeof(x)) < (ssize_t)sizeof(x)) {
271                 return ERROR_IO;
272             }
273 
274             *size = ntohs(x);
275             break;
276         }
277 
278         case 8:
279         {
280             uint8_t x;
281             if (mTable->mDataSource->readAt(
282                         mTable->mSampleSizeOffset + 12 + sampleIndex,
283                         &x, sizeof(x)) < (ssize_t)sizeof(x)) {
284                 return ERROR_IO;
285             }
286 
287             *size = x;
288             break;
289         }
290 
291         default:
292         {
293             CHECK_EQ(mTable->mSampleSizeFieldSize, 4u);
294 
295             uint8_t x;
296             if (mTable->mDataSource->readAt(
297                         mTable->mSampleSizeOffset + 12 + sampleIndex / 2,
298                         &x, sizeof(x)) < (ssize_t)sizeof(x)) {
299                 return ERROR_IO;
300             }
301 
302             *size = (sampleIndex & 1) ? x & 0x0f : x >> 4;
303             break;
304         }
305     }
306 
307     return OK;
308 }
309 
findSampleTimeAndDuration(uint32_t sampleIndex,uint64_t * time,uint64_t * duration)310 status_t SampleIterator::findSampleTimeAndDuration(
311         uint32_t sampleIndex, uint64_t *time, uint64_t *duration) {
312     if (sampleIndex >= mTable->mNumSampleSizes) {
313         return ERROR_OUT_OF_RANGE;
314     }
315 
316     while (true) {
317         if (mTTSSampleIndex > UINT32_MAX - mTTSCount) {
318             return ERROR_OUT_OF_RANGE;
319         }
320         if(sampleIndex < mTTSSampleIndex + mTTSCount) {
321             break;
322         }
323         if (mTimeToSampleIndex == mTable->mTimeToSampleCount ||
324             (mTTSDuration != 0 && mTTSCount > UINT64_MAX / mTTSDuration) ||
325             mTTSSampleTime > UINT64_MAX - (mTTSCount * mTTSDuration)) {
326             return ERROR_OUT_OF_RANGE;
327         }
328 
329         mTTSSampleIndex += mTTSCount;
330         mTTSSampleTime += mTTSCount * mTTSDuration;
331 
332         mTTSCount = mTable->mTimeToSample[2 * mTimeToSampleIndex];
333         mTTSDuration = mTable->mTimeToSample[2 * mTimeToSampleIndex + 1];
334 
335         ++mTimeToSampleIndex;
336     }
337 
338     // below is equivalent to:
339     // *time = mTTSSampleTime + mTTSDuration * (sampleIndex - mTTSSampleIndex);
340     uint64_t tmp;
341     if (__builtin_sub_overflow(sampleIndex, mTTSSampleIndex, &tmp) ||
342             __builtin_mul_overflow(mTTSDuration, tmp, &tmp) ||
343             __builtin_add_overflow(mTTSSampleTime, tmp, &tmp)) {
344         return ERROR_OUT_OF_RANGE;
345     }
346     *time = tmp;
347 
348     int32_t offset = mTable->getCompositionTimeOffset(sampleIndex);
349     if ((offset < 0 && *time < (offset == INT32_MIN ?
350             INT64_MAX : uint64_t(-offset))) ||
351             (offset > 0 && *time > UINT64_MAX - offset)) {
352         ALOGE("%llu + %d would overflow", (unsigned long long) *time, offset);
353         return ERROR_OUT_OF_RANGE;
354     }
355     if (offset > 0) {
356         *time += offset;
357     } else {
358         *time -= (offset == INT64_MIN ? INT64_MAX : (-offset));
359     }
360 
361     *duration = mTTSDuration;
362 
363     return OK;
364 }
365 
366 }  // namespace android
367 
368