blob: a4d3994bb3708db1302495c4d5e8ed47143da68c [file] [log] [blame]
Andreas Huber20111aa2009-07-14 16:56:47 -07001/*
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"
Andreas Huberc57b6792010-01-19 10:39:21 -080018//#define LOG_NDEBUG 0
Andreas Huber20111aa2009-07-14 16:56:47 -070019#include <utils/Log.h>
20
Wonsik Kim1ab38dc2016-07-21 14:43:38 +090021#include <limits>
22
Marco Nelissen75226172016-11-16 14:10:52 -080023#include "SampleTable.h"
24#include "SampleIterator.h"
Andreas Huber89e69da2009-10-13 10:22:55 -070025
Andreas Huber20111aa2009-07-14 16:56:47 -070026#include <arpa/inet.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070027
Marco Nelissencec44d02018-06-17 22:21:09 -070028#include <media/MediaExtractorPluginApi.h>
Andreas Huber89aa8fe2011-09-19 12:18:47 -070029#include <media/stagefright/foundation/ADebug.h>
Dongwon Kang60761282017-10-09 11:16:48 -070030#include <media/stagefright/foundation/ByteUtils.h>
Andreas Huber20111aa2009-07-14 16:56:47 -070031
Wei Jia3564c452015-08-18 11:17:24 -070032/* TODO: remove after being merged into other branches */
33#ifndef UINT32_MAX
34#define UINT32_MAX (4294967295U)
35#endif
36
Andreas Huber20111aa2009-07-14 16:56:47 -070037namespace android {
38
Andreas Huberc57b6792010-01-19 10:39:21 -080039// static
Marco Nelissen51087de2019-01-22 15:39:07 -080040const uint32_t SampleTable::kChunkOffsetType32 = FOURCC("stco");
Andreas Huberc57b6792010-01-19 10:39:21 -080041// static
Marco Nelissen51087de2019-01-22 15:39:07 -080042const uint32_t SampleTable::kChunkOffsetType64 = FOURCC("co64");
Andreas Huberc57b6792010-01-19 10:39:21 -080043// static
Marco Nelissen51087de2019-01-22 15:39:07 -080044const uint32_t SampleTable::kSampleSizeType32 = FOURCC("stsz");
Andreas Huberc57b6792010-01-19 10:39:21 -080045// static
Marco Nelissen51087de2019-01-22 15:39:07 -080046const uint32_t SampleTable::kSampleSizeTypeCompact = FOURCC("stz2");
Andreas Huberc57b6792010-01-19 10:39:21 -080047
48////////////////////////////////////////////////////////////////////////////////
Andreas Huber20111aa2009-07-14 16:56:47 -070049
Wonsik Kim1ab38dc2016-07-21 14:43:38 +090050const off64_t kMaxOffset = std::numeric_limits<off64_t>::max();
51
Andreas Huber89aa8fe2011-09-19 12:18:47 -070052struct SampleTable::CompositionDeltaLookup {
53 CompositionDeltaLookup();
54
55 void setEntries(
Marco Nelissenb1dc9e02016-02-17 10:37:29 -080056 const int32_t *deltaEntries, size_t numDeltaEntries);
Andreas Huber89aa8fe2011-09-19 12:18:47 -070057
Marco Nelissenb1dc9e02016-02-17 10:37:29 -080058 int32_t getCompositionTimeOffset(uint32_t sampleIndex);
Andreas Huber89aa8fe2011-09-19 12:18:47 -070059
60private:
61 Mutex mLock;
62
Marco Nelissenb1dc9e02016-02-17 10:37:29 -080063 const int32_t *mDeltaEntries;
Andreas Huber89aa8fe2011-09-19 12:18:47 -070064 size_t mNumDeltaEntries;
65
66 size_t mCurrentDeltaEntry;
67 size_t mCurrentEntrySampleIndex;
68
69 DISALLOW_EVIL_CONSTRUCTORS(CompositionDeltaLookup);
70};
71
72SampleTable::CompositionDeltaLookup::CompositionDeltaLookup()
73 : mDeltaEntries(NULL),
74 mNumDeltaEntries(0),
75 mCurrentDeltaEntry(0),
76 mCurrentEntrySampleIndex(0) {
77}
78
79void SampleTable::CompositionDeltaLookup::setEntries(
Marco Nelissenb1dc9e02016-02-17 10:37:29 -080080 const int32_t *deltaEntries, size_t numDeltaEntries) {
Andreas Huber89aa8fe2011-09-19 12:18:47 -070081 Mutex::Autolock autolock(mLock);
82
83 mDeltaEntries = deltaEntries;
84 mNumDeltaEntries = numDeltaEntries;
85 mCurrentDeltaEntry = 0;
86 mCurrentEntrySampleIndex = 0;
87}
88
Marco Nelissenb1dc9e02016-02-17 10:37:29 -080089int32_t SampleTable::CompositionDeltaLookup::getCompositionTimeOffset(
Andreas Huber89aa8fe2011-09-19 12:18:47 -070090 uint32_t sampleIndex) {
91 Mutex::Autolock autolock(mLock);
92
93 if (mDeltaEntries == NULL) {
94 return 0;
95 }
96
97 if (sampleIndex < mCurrentEntrySampleIndex) {
98 mCurrentDeltaEntry = 0;
99 mCurrentEntrySampleIndex = 0;
100 }
101
102 while (mCurrentDeltaEntry < mNumDeltaEntries) {
103 uint32_t sampleCount = mDeltaEntries[2 * mCurrentDeltaEntry];
104 if (sampleIndex < mCurrentEntrySampleIndex + sampleCount) {
105 return mDeltaEntries[2 * mCurrentDeltaEntry + 1];
106 }
107
108 mCurrentEntrySampleIndex += sampleCount;
109 ++mCurrentDeltaEntry;
110 }
111
112 return 0;
113}
114
115////////////////////////////////////////////////////////////////////////////////
116
Marco Nelissencec44d02018-06-17 22:21:09 -0700117SampleTable::SampleTable(DataSourceHelper *source)
Andreas Huber20111aa2009-07-14 16:56:47 -0700118 : mDataSource(source),
119 mChunkOffsetOffset(-1),
120 mChunkOffsetType(0),
121 mNumChunkOffsets(0),
122 mSampleToChunkOffset(-1),
123 mNumSampleToChunkOffsets(0),
124 mSampleSizeOffset(-1),
125 mSampleSizeFieldSize(0),
126 mDefaultSampleSize(0),
127 mNumSampleSizes(0),
Pawin Vongmasa70dec4d2016-04-20 15:51:48 -0700128 mHasTimeToSample(false),
Andreas Huber20111aa2009-07-14 16:56:47 -0700129 mTimeToSampleCount(0),
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700130 mTimeToSample(NULL),
Andreas Huber4678a6d2011-04-15 11:52:29 -0700131 mSampleTimeEntries(NULL),
Andreas Huber4931bb52011-02-03 13:18:16 -0800132 mCompositionTimeDeltaEntries(NULL),
133 mNumCompositionTimeDeltaEntries(0),
Andreas Huber89aa8fe2011-09-19 12:18:47 -0700134 mCompositionDeltaLookup(new CompositionDeltaLookup),
Andreas Huber20111aa2009-07-14 16:56:47 -0700135 mSyncSampleOffset(-1),
Andreas Huberc57b6792010-01-19 10:39:21 -0800136 mNumSyncSamples(0),
Andreas Huber8bf59e72010-08-06 14:13:10 -0700137 mSyncSamples(NULL),
138 mLastSyncSampleIndex(0),
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700139 mSampleToChunkEntries(NULL),
140 mTotalSize(0) {
Andreas Huberc57b6792010-01-19 10:39:21 -0800141 mSampleIterator = new SampleIterator(this);
Andreas Huber20111aa2009-07-14 16:56:47 -0700142}
143
144SampleTable::~SampleTable() {
Andreas Huberc57b6792010-01-19 10:39:21 -0800145 delete[] mSampleToChunkEntries;
146 mSampleToChunkEntries = NULL;
147
Andreas Huber8bf59e72010-08-06 14:13:10 -0700148 delete[] mSyncSamples;
149 mSyncSamples = NULL;
150
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700151 delete[] mTimeToSample;
152 mTimeToSample = NULL;
153
Andreas Huber89aa8fe2011-09-19 12:18:47 -0700154 delete mCompositionDeltaLookup;
155 mCompositionDeltaLookup = NULL;
156
Andreas Huber4931bb52011-02-03 13:18:16 -0800157 delete[] mCompositionTimeDeltaEntries;
158 mCompositionTimeDeltaEntries = NULL;
159
Andreas Huber4678a6d2011-04-15 11:52:29 -0700160 delete[] mSampleTimeEntries;
161 mSampleTimeEntries = NULL;
162
Andreas Huberc57b6792010-01-19 10:39:21 -0800163 delete mSampleIterator;
164 mSampleIterator = NULL;
Andreas Huber20111aa2009-07-14 16:56:47 -0700165}
166
Andreas Huber169c2862011-08-17 13:03:51 -0700167bool SampleTable::isValid() const {
168 return mChunkOffsetOffset >= 0
169 && mSampleToChunkOffset >= 0
170 && mSampleSizeOffset >= 0
Pawin Vongmasa70dec4d2016-04-20 15:51:48 -0700171 && mHasTimeToSample;
Andreas Huber169c2862011-08-17 13:03:51 -0700172}
173
Andreas Huber20111aa2009-07-14 16:56:47 -0700174status_t SampleTable::setChunkOffsetParams(
James Dongc7fc37a2010-11-16 14:04:54 -0800175 uint32_t type, off64_t data_offset, size_t data_size) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700176 if (mChunkOffsetOffset >= 0) {
177 return ERROR_MALFORMED;
178 }
179
Andreas Huber0c891992009-08-26 14:48:20 -0700180 CHECK(type == kChunkOffsetType32 || type == kChunkOffsetType64);
Andreas Huber20111aa2009-07-14 16:56:47 -0700181
182 mChunkOffsetOffset = data_offset;
183 mChunkOffsetType = type;
184
185 if (data_size < 8) {
186 return ERROR_MALFORMED;
187 }
188
189 uint8_t header[8];
Andreas Huber34769bc2009-10-23 10:22:30 -0700190 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -0700191 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 mNumChunkOffsets = U32_AT(&header[4]);
201
202 if (mChunkOffsetType == kChunkOffsetType32) {
Dan Austinffd79502015-10-16 12:22:09 -0700203 if ((data_size - 8) / 4 < mNumChunkOffsets) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700204 return ERROR_MALFORMED;
205 }
206 } else {
Dan Austinffd79502015-10-16 12:22:09 -0700207 if ((data_size - 8) / 8 < mNumChunkOffsets) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700208 return ERROR_MALFORMED;
209 }
210 }
211
212 return OK;
213}
214
215status_t SampleTable::setSampleToChunkParams(
James Dongc7fc37a2010-11-16 14:04:54 -0800216 off64_t data_offset, size_t data_size) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700217 if (mSampleToChunkOffset >= 0) {
Marco Nelissen1cb23b02016-03-21 09:29:06 -0700218 // already set
219 return ERROR_MALFORMED;
220 }
221
222 if (data_offset < 0) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700223 return ERROR_MALFORMED;
224 }
225
226 mSampleToChunkOffset = data_offset;
227
228 if (data_size < 8) {
229 return ERROR_MALFORMED;
230 }
231
232 uint8_t header[8];
Andreas Huber34769bc2009-10-23 10:22:30 -0700233 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -0700234 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
235 return ERROR_IO;
236 }
237
238 if (U32_AT(header) != 0) {
239 // Expected version = 0, flags = 0.
240 return ERROR_MALFORMED;
241 }
242
243 mNumSampleToChunkOffsets = U32_AT(&header[4]);
244
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900245 if ((data_size - 8) / sizeof(SampleToChunkEntry) < mNumSampleToChunkOffsets) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700246 return ERROR_MALFORMED;
247 }
248
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900249 if ((uint64_t)kMaxTotalSize / sizeof(SampleToChunkEntry) <=
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700250 (uint64_t)mNumSampleToChunkOffsets) {
251 ALOGE("Sample-to-chunk table size too large.");
Joshua J. Drakec24607c2015-04-08 23:44:57 -0500252 return ERROR_OUT_OF_RANGE;
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700253 }
254
255 mTotalSize += (uint64_t)mNumSampleToChunkOffsets *
256 sizeof(SampleToChunkEntry);
257 if (mTotalSize > kMaxTotalSize) {
258 ALOGE("Sample-to-chunk table size would make sample table too large.\n"
259 " Requested sample-to-chunk table size = %llu\n"
260 " Eventual sample table size >= %llu\n"
261 " Allowed sample table size = %llu\n",
262 (unsigned long long)mNumSampleToChunkOffsets *
263 sizeof(SampleToChunkEntry),
264 (unsigned long long)mTotalSize,
265 (unsigned long long)kMaxTotalSize);
266 return ERROR_OUT_OF_RANGE;
267 }
Joshua J. Drakec24607c2015-04-08 23:44:57 -0500268
Andreas Huberc57b6792010-01-19 10:39:21 -0800269 mSampleToChunkEntries =
Joshua J. Drakead435372015-04-08 23:31:25 -0500270 new (std::nothrow) SampleToChunkEntry[mNumSampleToChunkOffsets];
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700271 if (!mSampleToChunkEntries) {
272 ALOGE("Cannot allocate sample-to-chunk table with %llu entries.",
273 (unsigned long long)mNumSampleToChunkOffsets);
Joshua J. Drakead435372015-04-08 23:31:25 -0500274 return ERROR_OUT_OF_RANGE;
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700275 }
276
277 if (mNumSampleToChunkOffsets == 0) {
278 return OK;
279 }
280
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900281 if ((off64_t)(kMaxOffset - 8 -
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700282 ((mNumSampleToChunkOffsets - 1) * sizeof(SampleToChunkEntry)))
283 < mSampleToChunkOffset) {
284 return ERROR_MALFORMED;
285 }
Andreas Huberc57b6792010-01-19 10:39:21 -0800286
287 for (uint32_t i = 0; i < mNumSampleToChunkOffsets; ++i) {
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900288 uint8_t buffer[sizeof(SampleToChunkEntry)];
Dan Austinffd79502015-10-16 12:22:09 -0700289
Andreas Huberc57b6792010-01-19 10:39:21 -0800290 if (mDataSource->readAt(
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900291 mSampleToChunkOffset + 8 + i * sizeof(SampleToChunkEntry),
292 buffer,
293 sizeof(buffer))
Andreas Huberc57b6792010-01-19 10:39:21 -0800294 != (ssize_t)sizeof(buffer)) {
295 return ERROR_IO;
296 }
Marco Nelissendafa42d2015-09-08 13:19:44 -0700297 // chunk index is 1 based in the spec.
298 if (U32_AT(buffer) < 1) {
299 ALOGE("b/23534160");
300 return ERROR_OUT_OF_RANGE;
301 }
Andreas Huberc57b6792010-01-19 10:39:21 -0800302
303 // We want the chunk index to be 0-based.
304 mSampleToChunkEntries[i].startChunk = U32_AT(buffer) - 1;
305 mSampleToChunkEntries[i].samplesPerChunk = U32_AT(&buffer[4]);
306 mSampleToChunkEntries[i].chunkDesc = U32_AT(&buffer[8]);
307 }
308
Andreas Huber20111aa2009-07-14 16:56:47 -0700309 return OK;
310}
311
312status_t SampleTable::setSampleSizeParams(
James Dongc7fc37a2010-11-16 14:04:54 -0800313 uint32_t type, off64_t data_offset, size_t data_size) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700314 if (mSampleSizeOffset >= 0) {
315 return ERROR_MALFORMED;
316 }
317
Andreas Huber0c891992009-08-26 14:48:20 -0700318 CHECK(type == kSampleSizeType32 || type == kSampleSizeTypeCompact);
Andreas Huber20111aa2009-07-14 16:56:47 -0700319
320 mSampleSizeOffset = data_offset;
321
322 if (data_size < 12) {
323 return ERROR_MALFORMED;
324 }
325
326 uint8_t header[12];
Andreas Huber34769bc2009-10-23 10:22:30 -0700327 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -0700328 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
329 return ERROR_IO;
330 }
331
332 if (U32_AT(header) != 0) {
333 // Expected version = 0, flags = 0.
334 return ERROR_MALFORMED;
335 }
336
337 mDefaultSampleSize = U32_AT(&header[4]);
338 mNumSampleSizes = U32_AT(&header[8]);
Wei Jia3564c452015-08-18 11:17:24 -0700339 if (mNumSampleSizes > (UINT32_MAX - 12) / 16) {
Wei Jiac27cee32016-03-24 09:41:24 -0700340 ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
Wei Jia3564c452015-08-18 11:17:24 -0700341 return ERROR_MALFORMED;
342 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700343
344 if (type == kSampleSizeType32) {
345 mSampleSizeFieldSize = 32;
346
347 if (mDefaultSampleSize != 0) {
348 return OK;
349 }
350
351 if (data_size < 12 + mNumSampleSizes * 4) {
352 return ERROR_MALFORMED;
353 }
354 } else {
355 if ((mDefaultSampleSize & 0xffffff00) != 0) {
356 // The high 24 bits are reserved and must be 0.
357 return ERROR_MALFORMED;
358 }
359
Andreas Huber9f753df2011-05-12 13:38:20 -0700360 mSampleSizeFieldSize = mDefaultSampleSize & 0xff;
Andreas Huber20111aa2009-07-14 16:56:47 -0700361 mDefaultSampleSize = 0;
362
363 if (mSampleSizeFieldSize != 4 && mSampleSizeFieldSize != 8
364 && mSampleSizeFieldSize != 16) {
365 return ERROR_MALFORMED;
366 }
367
368 if (data_size < 12 + (mNumSampleSizes * mSampleSizeFieldSize + 4) / 8) {
369 return ERROR_MALFORMED;
370 }
371 }
372
373 return OK;
374}
375
376status_t SampleTable::setTimeToSampleParams(
James Dongc7fc37a2010-11-16 14:04:54 -0800377 off64_t data_offset, size_t data_size) {
Pawin Vongmasa70dec4d2016-04-20 15:51:48 -0700378 if (mHasTimeToSample || data_size < 8) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700379 return ERROR_MALFORMED;
380 }
381
382 uint8_t header[8];
Andreas Huber34769bc2009-10-23 10:22:30 -0700383 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -0700384 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
385 return ERROR_IO;
386 }
387
388 if (U32_AT(header) != 0) {
389 // Expected version = 0, flags = 0.
390 return ERROR_MALFORMED;
391 }
392
393 mTimeToSampleCount = U32_AT(&header[4]);
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900394 if (mTimeToSampleCount > UINT32_MAX / (2 * sizeof(uint32_t))) {
Pawin Vongmasaa3630a42016-04-13 16:25:12 -0700395 // Choose this bound because
396 // 1) 2 * sizeof(uint32_t) is the amount of memory needed for one
397 // time-to-sample entry in the time-to-sample table.
398 // 2) mTimeToSampleCount is the number of entries of the time-to-sample
399 // table.
400 // 3) We hope that the table size does not exceed UINT32_MAX.
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700401 ALOGE("Time-to-sample table size too large.");
Robert Shihedd4a762014-07-28 09:54:57 -0700402 return ERROR_OUT_OF_RANGE;
403 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700404
Pawin Vongmasaa3630a42016-04-13 16:25:12 -0700405 // Note: At this point, we know that mTimeToSampleCount * 2 will not
406 // overflow because of the above condition.
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700407
408 uint64_t allocSize = (uint64_t)mTimeToSampleCount * 2 * sizeof(uint32_t);
409 mTotalSize += allocSize;
410 if (mTotalSize > kMaxTotalSize) {
411 ALOGE("Time-to-sample table size would make sample table too large.\n"
412 " Requested time-to-sample table size = %llu\n"
413 " Eventual sample table size >= %llu\n"
414 " Allowed sample table size = %llu\n",
415 (unsigned long long)allocSize,
416 (unsigned long long)mTotalSize,
417 (unsigned long long)kMaxTotalSize);
418 return ERROR_OUT_OF_RANGE;
419 }
420
421 mTimeToSample = new (std::nothrow) uint32_t[mTimeToSampleCount * 2];
422 if (!mTimeToSample) {
423 ALOGE("Cannot allocate time-to-sample table with %llu entries.",
424 (unsigned long long)mTimeToSampleCount);
425 return ERROR_OUT_OF_RANGE;
426 }
427
428 if (mDataSource->readAt(data_offset + 8, mTimeToSample,
429 (size_t)allocSize) < (ssize_t)allocSize) {
430 ALOGE("Incomplete data read for time-to-sample table.");
Andreas Huber20111aa2009-07-14 16:56:47 -0700431 return ERROR_IO;
432 }
433
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700434 for (size_t i = 0; i < mTimeToSampleCount * 2; ++i) {
435 mTimeToSample[i] = ntohl(mTimeToSample[i]);
Andreas Huber20111aa2009-07-14 16:56:47 -0700436 }
Pawin Vongmasa70dec4d2016-04-20 15:51:48 -0700437
438 mHasTimeToSample = true;
Andreas Huber20111aa2009-07-14 16:56:47 -0700439 return OK;
440}
441
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800442// NOTE: per 14996-12, version 0 ctts contains unsigned values, while version 1
443// contains signed values, however some software creates version 0 files that
444// contain signed values, so we're always treating the values as signed,
445// regardless of version.
Andreas Huber4931bb52011-02-03 13:18:16 -0800446status_t SampleTable::setCompositionTimeToSampleParams(
447 off64_t data_offset, size_t data_size) {
Steve Blockdf64d152012-01-04 20:05:49 +0000448 ALOGI("There are reordered frames present.");
Andreas Huber4931bb52011-02-03 13:18:16 -0800449
450 if (mCompositionTimeDeltaEntries != NULL || data_size < 8) {
451 return ERROR_MALFORMED;
452 }
453
454 uint8_t header[8];
455 if (mDataSource->readAt(
456 data_offset, header, sizeof(header))
457 < (ssize_t)sizeof(header)) {
458 return ERROR_IO;
459 }
460
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800461 uint32_t flags = U32_AT(header);
462 uint32_t version = flags >> 24;
463 flags &= 0xffffff;
464
465 if ((version != 0 && version != 1) || flags != 0) {
466 // Expected version = 0 or 1, flags = 0.
Andreas Huber4931bb52011-02-03 13:18:16 -0800467 return ERROR_MALFORMED;
468 }
469
470 size_t numEntries = U32_AT(&header[4]);
471
Dan Austinffd79502015-10-16 12:22:09 -0700472 if (((SIZE_MAX / 8) - 1 < numEntries) || (data_size != (numEntries + 1) * 8)) {
Andreas Huber4931bb52011-02-03 13:18:16 -0800473 return ERROR_MALFORMED;
474 }
475
476 mNumCompositionTimeDeltaEntries = numEntries;
Pawin Vongmasa978a6cd2016-07-11 18:41:33 -0700477 uint64_t allocSize = (uint64_t)numEntries * 2 * sizeof(int32_t);
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900478 if (allocSize > kMaxTotalSize) {
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700479 ALOGE("Composition-time-to-sample table size too large.");
Robert Shihedd4a762014-07-28 09:54:57 -0700480 return ERROR_OUT_OF_RANGE;
481 }
482
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700483 mTotalSize += allocSize;
484 if (mTotalSize > kMaxTotalSize) {
485 ALOGE("Composition-time-to-sample table would make sample table too large.\n"
486 " Requested composition-time-to-sample table size = %llu\n"
487 " Eventual sample table size >= %llu\n"
488 " Allowed sample table size = %llu\n",
489 (unsigned long long)allocSize,
490 (unsigned long long)mTotalSize,
491 (unsigned long long)kMaxTotalSize);
Andreas Huber4931bb52011-02-03 13:18:16 -0800492 return ERROR_OUT_OF_RANGE;
493 }
494
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800495 mCompositionTimeDeltaEntries = new (std::nothrow) int32_t[2 * numEntries];
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700496 if (!mCompositionTimeDeltaEntries) {
497 ALOGE("Cannot allocate composition-time-to-sample table with %llu "
498 "entries.", (unsigned long long)numEntries);
Joshua J. Drakead435372015-04-08 23:31:25 -0500499 return ERROR_OUT_OF_RANGE;
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700500 }
Andreas Huber4931bb52011-02-03 13:18:16 -0800501
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700502 if (mDataSource->readAt(data_offset + 8, mCompositionTimeDeltaEntries,
503 (size_t)allocSize) < (ssize_t)allocSize) {
Andreas Huber4931bb52011-02-03 13:18:16 -0800504 delete[] mCompositionTimeDeltaEntries;
505 mCompositionTimeDeltaEntries = NULL;
506
507 return ERROR_IO;
508 }
509
510 for (size_t i = 0; i < 2 * numEntries; ++i) {
511 mCompositionTimeDeltaEntries[i] = ntohl(mCompositionTimeDeltaEntries[i]);
512 }
513
Andreas Huber89aa8fe2011-09-19 12:18:47 -0700514 mCompositionDeltaLookup->setEntries(
515 mCompositionTimeDeltaEntries, mNumCompositionTimeDeltaEntries);
516
Andreas Huber4931bb52011-02-03 13:18:16 -0800517 return OK;
518}
519
James Dongc7fc37a2010-11-16 14:04:54 -0800520status_t SampleTable::setSyncSampleParams(off64_t data_offset, size_t data_size) {
Andreas Huber20111aa2009-07-14 16:56:47 -0700521 if (mSyncSampleOffset >= 0 || data_size < 8) {
522 return ERROR_MALFORMED;
523 }
524
Andreas Huber20111aa2009-07-14 16:56:47 -0700525 uint8_t header[8];
Andreas Huber34769bc2009-10-23 10:22:30 -0700526 if (mDataSource->readAt(
Andreas Huber20111aa2009-07-14 16:56:47 -0700527 data_offset, header, sizeof(header)) < (ssize_t)sizeof(header)) {
528 return ERROR_IO;
529 }
530
531 if (U32_AT(header) != 0) {
532 // Expected version = 0, flags = 0.
533 return ERROR_MALFORMED;
534 }
535
Marco Nelissena9660fe2017-01-12 15:49:04 -0800536 uint32_t numSyncSamples = U32_AT(&header[4]);
Andreas Huber20111aa2009-07-14 16:56:47 -0700537
Marco Nelissena9660fe2017-01-12 15:49:04 -0800538 if (numSyncSamples < 2) {
Steve Block3856b092011-10-20 11:56:00 +0100539 ALOGV("Table of sync samples is empty or has only a single entry!");
Andreas Huber20111aa2009-07-14 16:56:47 -0700540 }
Andreas Huber8bf59e72010-08-06 14:13:10 -0700541
Marco Nelissena9660fe2017-01-12 15:49:04 -0800542 uint64_t allocSize = (uint64_t)numSyncSamples * sizeof(uint32_t);
Wonsik Kim1ab38dc2016-07-21 14:43:38 +0900543 if (allocSize > kMaxTotalSize) {
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700544 ALOGE("Sync sample table size too large.");
Robert Shihedd4a762014-07-28 09:54:57 -0700545 return ERROR_OUT_OF_RANGE;
546 }
547
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700548 mTotalSize += allocSize;
549 if (mTotalSize > kMaxTotalSize) {
550 ALOGE("Sync sample table size would make sample table too large.\n"
551 " Requested sync sample table size = %llu\n"
552 " Eventual sample table size >= %llu\n"
553 " Allowed sample table size = %llu\n",
554 (unsigned long long)allocSize,
555 (unsigned long long)mTotalSize,
556 (unsigned long long)kMaxTotalSize);
Andreas Huber20111aa2009-07-14 16:56:47 -0700557 return ERROR_OUT_OF_RANGE;
558 }
559
Marco Nelissena9660fe2017-01-12 15:49:04 -0800560 mSyncSamples = new (std::nothrow) uint32_t[numSyncSamples];
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700561 if (!mSyncSamples) {
562 ALOGE("Cannot allocate sync sample table with %llu entries.",
Marco Nelissena9660fe2017-01-12 15:49:04 -0800563 (unsigned long long)numSyncSamples);
Joshua J. Drakead435372015-04-08 23:31:25 -0500564 return ERROR_OUT_OF_RANGE;
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700565 }
Joshua J. Drakead435372015-04-08 23:31:25 -0500566
Marco Nelissena9660fe2017-01-12 15:49:04 -0800567 if (mDataSource->readAt(data_offset + 8, mSyncSamples,
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700568 (size_t)allocSize) != (ssize_t)allocSize) {
Caroline Tice158c1972017-01-17 16:33:03 -0800569 delete[] mSyncSamples;
Marco Nelissena9660fe2017-01-12 15:49:04 -0800570 mSyncSamples = NULL;
Andreas Huber20111aa2009-07-14 16:56:47 -0700571 return ERROR_IO;
572 }
573
Marco Nelissena9660fe2017-01-12 15:49:04 -0800574 for (size_t i = 0; i < numSyncSamples; ++i) {
Roger1 Jonsson69861652016-10-26 09:20:00 +0200575 if (mSyncSamples[i] == 0) {
576 ALOGE("b/32423862, unexpected zero value in stss");
577 continue;
578 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700579 mSyncSamples[i] = ntohl(mSyncSamples[i]) - 1;
580 }
581
Marco Nelissena9660fe2017-01-12 15:49:04 -0800582 mSyncSampleOffset = data_offset;
583 mNumSyncSamples = numSyncSamples;
584
Andreas Huber20111aa2009-07-14 16:56:47 -0700585 return OK;
586}
587
588uint32_t SampleTable::countChunkOffsets() const {
589 return mNumChunkOffsets;
590}
591
Andreas Huber20111aa2009-07-14 16:56:47 -0700592uint32_t SampleTable::countSamples() const {
593 return mNumSampleSizes;
594}
595
Andreas Huber20111aa2009-07-14 16:56:47 -0700596status_t SampleTable::getMaxSampleSize(size_t *max_size) {
597 Mutex::Autolock autoLock(mLock);
598
599 *max_size = 0;
600
601 for (uint32_t i = 0; i < mNumSampleSizes; ++i) {
602 size_t sample_size;
Andreas Huberc57b6792010-01-19 10:39:21 -0800603 status_t err = getSampleSize_l(i, &sample_size);
Andreas Huberda76c642010-01-14 11:36:45 -0800604
Andreas Huber20111aa2009-07-14 16:56:47 -0700605 if (err != OK) {
606 return err;
607 }
608
609 if (sample_size > *max_size) {
610 *max_size = sample_size;
611 }
612 }
613
614 return OK;
615}
616
wuhuang12de2b92019-01-18 17:14:03 +0800617uint32_t abs_difference(uint64_t time1, uint64_t time2) {
Andreas Huberda76c642010-01-14 11:36:45 -0800618 return time1 > time2 ? time1 - time2 : time2 - time1;
619}
620
Andreas Huber4678a6d2011-04-15 11:52:29 -0700621// static
622int SampleTable::CompareIncreasingTime(const void *_a, const void *_b) {
623 const SampleTimeEntry *a = (const SampleTimeEntry *)_a;
624 const SampleTimeEntry *b = (const SampleTimeEntry *)_b;
Andreas Huber4931bb52011-02-03 13:18:16 -0800625
Andreas Huber4678a6d2011-04-15 11:52:29 -0700626 if (a->mCompositionTime < b->mCompositionTime) {
627 return -1;
628 } else if (a->mCompositionTime > b->mCompositionTime) {
629 return 1;
630 }
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700631
Andreas Huber4678a6d2011-04-15 11:52:29 -0700632 return 0;
633}
634
635void SampleTable::buildSampleEntriesTable() {
Andreas Huber20111aa2009-07-14 16:56:47 -0700636 Mutex::Autolock autoLock(mLock);
637
Wei Jia3564c452015-08-18 11:17:24 -0700638 if (mSampleTimeEntries != NULL || mNumSampleSizes == 0) {
Wei Jiacccd2e52016-03-24 10:58:04 -0700639 if (mNumSampleSizes == 0) {
640 ALOGE("b/23247055, mNumSampleSizes(%u)", mNumSampleSizes);
641 }
Andreas Huber4678a6d2011-04-15 11:52:29 -0700642 return;
643 }
644
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700645 mTotalSize += (uint64_t)mNumSampleSizes * sizeof(SampleTimeEntry);
646 if (mTotalSize > kMaxTotalSize) {
647 ALOGE("Sample entry table size would make sample table too large.\n"
648 " Requested sample entry table size = %llu\n"
649 " Eventual sample table size >= %llu\n"
650 " Allowed sample table size = %llu\n",
651 (unsigned long long)mNumSampleSizes * sizeof(SampleTimeEntry),
652 (unsigned long long)mTotalSize,
653 (unsigned long long)kMaxTotalSize);
Joshua J. Drakead435372015-04-08 23:31:25 -0500654 return;
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700655 }
656
657 mSampleTimeEntries = new (std::nothrow) SampleTimeEntry[mNumSampleSizes];
Iris Changfe5cd492019-10-20 12:10:12 +0800658
Pawin Vongmasa583a0122016-06-21 19:10:21 -0700659 if (!mSampleTimeEntries) {
660 ALOGE("Cannot allocate sample entry table with %llu entries.",
661 (unsigned long long)mNumSampleSizes);
662 return;
663 }
Iris Changfe5cd492019-10-20 12:10:12 +0800664 memset(mSampleTimeEntries, 0, sizeof(SampleTimeEntry) * mNumSampleSizes);
Andreas Huber4678a6d2011-04-15 11:52:29 -0700665
666 uint32_t sampleIndex = 0;
wuhuang12de2b92019-01-18 17:14:03 +0800667 uint64_t sampleTime = 0;
Andreas Huber4678a6d2011-04-15 11:52:29 -0700668
Andreas Huber20111aa2009-07-14 16:56:47 -0700669 for (uint32_t i = 0; i < mTimeToSampleCount; ++i) {
670 uint32_t n = mTimeToSample[2 * i];
671 uint32_t delta = mTimeToSample[2 * i + 1];
672
Andreas Huber4678a6d2011-04-15 11:52:29 -0700673 for (uint32_t j = 0; j < n; ++j) {
Andreas Huber65a26702011-06-21 11:38:01 -0700674 if (sampleIndex < mNumSampleSizes) {
675 // Technically this should always be the case if the file
676 // is well-formed, but you know... there's (gasp) malformed
677 // content out there.
Andreas Huber20111aa2009-07-14 16:56:47 -0700678
Andreas Huber65a26702011-06-21 11:38:01 -0700679 mSampleTimeEntries[sampleIndex].mSampleIndex = sampleIndex;
Andreas Huberda76c642010-01-14 11:36:45 -0800680
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800681 int32_t compTimeDelta =
Andreas Huber89aa8fe2011-09-19 12:18:47 -0700682 mCompositionDeltaLookup->getCompositionTimeOffset(
683 sampleIndex);
684
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800685 if ((compTimeDelta < 0 && sampleTime <
686 (compTimeDelta == INT32_MIN ?
687 INT32_MAX : uint32_t(-compTimeDelta)))
688 || (compTimeDelta > 0 &&
wuhuang12de2b92019-01-18 17:14:03 +0800689 sampleTime > UINT64_MAX - compTimeDelta)) {
690 ALOGE("%llu + %d would overflow, clamping",
691 (unsigned long long) sampleTime, compTimeDelta);
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800692 if (compTimeDelta < 0) {
693 sampleTime = 0;
694 } else {
wuhuang12de2b92019-01-18 17:14:03 +0800695 sampleTime = UINT64_MAX;
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800696 }
697 compTimeDelta = 0;
698 }
699
Andreas Huber65a26702011-06-21 11:38:01 -0700700 mSampleTimeEntries[sampleIndex].mCompositionTime =
Marco Nelissenb1dc9e02016-02-17 10:37:29 -0800701 compTimeDelta > 0 ? sampleTime + compTimeDelta:
702 sampleTime - (-compTimeDelta);
Andreas Huber65a26702011-06-21 11:38:01 -0700703 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700704
Andreas Huber4678a6d2011-04-15 11:52:29 -0700705 ++sampleIndex;
wuhuang12de2b92019-01-18 17:14:03 +0800706 if (sampleTime > UINT64_MAX - delta) {
707 ALOGE("%llu + %u would overflow, clamping",
708 (unsigned long long) sampleTime, delta);
709 sampleTime = UINT64_MAX;
Bartosz Bialeked802762017-03-03 12:55:25 +0100710 } else {
711 sampleTime += delta;
712 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700713 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700714 }
715
Andreas Huber4678a6d2011-04-15 11:52:29 -0700716 qsort(mSampleTimeEntries, mNumSampleSizes, sizeof(SampleTimeEntry),
717 CompareIncreasingTime);
718}
719
720status_t SampleTable::findSampleAtTime(
Lajos Molnar599950e2014-07-17 10:52:36 -0700721 uint64_t req_time, uint64_t scale_num, uint64_t scale_den,
722 uint32_t *sample_index, uint32_t flags) {
Andreas Huber4678a6d2011-04-15 11:52:29 -0700723 buildSampleEntriesTable();
724
Wei Jia3564c452015-08-18 11:17:24 -0700725 if (mSampleTimeEntries == NULL) {
726 return ERROR_OUT_OF_RANGE;
727 }
728
Chong Zhangd3e0d862017-10-03 13:17:13 -0700729 if (flags == kFlagFrameIndex) {
730 if (req_time >= mNumSampleSizes) {
731 return ERROR_OUT_OF_RANGE;
732 }
733 *sample_index = mSampleTimeEntries[req_time].mSampleIndex;
734 return OK;
735 }
736
Andreas Huber4678a6d2011-04-15 11:52:29 -0700737 uint32_t left = 0;
Lajos Molnar225d5b22014-07-21 13:47:21 -0700738 uint32_t right_plus_one = mNumSampleSizes;
739 while (left < right_plus_one) {
740 uint32_t center = left + (right_plus_one - left) / 2;
Lajos Molnar599950e2014-07-17 10:52:36 -0700741 uint64_t centerTime =
742 getSampleTime(center, scale_num, scale_den);
Andreas Huber4678a6d2011-04-15 11:52:29 -0700743
744 if (req_time < centerTime) {
Lajos Molnar225d5b22014-07-21 13:47:21 -0700745 right_plus_one = center;
Andreas Huber4678a6d2011-04-15 11:52:29 -0700746 } else if (req_time > centerTime) {
747 left = center + 1;
748 } else {
Lajos Molnar599950e2014-07-17 10:52:36 -0700749 *sample_index = mSampleTimeEntries[center].mSampleIndex;
750 return OK;
Andreas Huber4678a6d2011-04-15 11:52:29 -0700751 }
752 }
753
Andreas Huber4678a6d2011-04-15 11:52:29 -0700754 uint32_t closestIndex = left;
755
Lajos Molnar599950e2014-07-17 10:52:36 -0700756 if (closestIndex == mNumSampleSizes) {
757 if (flags == kFlagAfter) {
758 return ERROR_OUT_OF_RANGE;
759 }
760 flags = kFlagBefore;
761 } else if (closestIndex == 0) {
762 if (flags == kFlagBefore) {
763 // normally we should return out of range, but that is
764 // treated as end-of-stream. instead return first sample
765 //
766 // return ERROR_OUT_OF_RANGE;
767 }
768 flags = kFlagAfter;
769 }
770
Andreas Huber4678a6d2011-04-15 11:52:29 -0700771 switch (flags) {
772 case kFlagBefore:
773 {
Lajos Molnar599950e2014-07-17 10:52:36 -0700774 --closestIndex;
Andreas Huber4678a6d2011-04-15 11:52:29 -0700775 break;
776 }
777
778 case kFlagAfter:
779 {
Lajos Molnar599950e2014-07-17 10:52:36 -0700780 // nothing to do
Andreas Huber4678a6d2011-04-15 11:52:29 -0700781 break;
782 }
783
784 default:
785 {
786 CHECK(flags == kFlagClosest);
Lajos Molnar599950e2014-07-17 10:52:36 -0700787 // pick closest based on timestamp. use abs_difference for safety
788 if (abs_difference(
789 getSampleTime(closestIndex, scale_num, scale_den), req_time) >
790 abs_difference(
791 req_time, getSampleTime(closestIndex - 1, scale_num, scale_den))) {
792 --closestIndex;
Andreas Huber4678a6d2011-04-15 11:52:29 -0700793 }
Andreas Huber4678a6d2011-04-15 11:52:29 -0700794 break;
795 }
796 }
797
798 *sample_index = mSampleTimeEntries[closestIndex].mSampleIndex;
Andreas Huber4678a6d2011-04-15 11:52:29 -0700799 return OK;
Andreas Huber20111aa2009-07-14 16:56:47 -0700800}
801
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700802status_t SampleTable::findSyncSampleNear(
803 uint32_t start_sample_index, uint32_t *sample_index, uint32_t flags) {
804 Mutex::Autolock autoLock(mLock);
805
Andreas Huber20111aa2009-07-14 16:56:47 -0700806 *sample_index = 0;
807
808 if (mSyncSampleOffset < 0) {
809 // All samples are sync-samples.
810 *sample_index = start_sample_index;
811 return OK;
812 }
813
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700814 if (mNumSyncSamples == 0) {
815 *sample_index = 0;
816 return OK;
817 }
Andreas Huberda76c642010-01-14 11:36:45 -0800818
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700819 uint32_t left = 0;
Lajos Molnar225d5b22014-07-21 13:47:21 -0700820 uint32_t right_plus_one = mNumSyncSamples;
821 while (left < right_plus_one) {
822 uint32_t center = left + (right_plus_one - left) / 2;
Andreas Huber8f76ebf2011-11-07 11:38:14 -0800823 uint32_t x = mSyncSamples[center];
Andreas Huber20111aa2009-07-14 16:56:47 -0700824
Andreas Huber8f76ebf2011-11-07 11:38:14 -0800825 if (start_sample_index < x) {
Lajos Molnar225d5b22014-07-21 13:47:21 -0700826 right_plus_one = center;
Andreas Huber8f76ebf2011-11-07 11:38:14 -0800827 } else if (start_sample_index > x) {
828 left = center + 1;
829 } else {
Lajos Molnar599950e2014-07-17 10:52:36 -0700830 *sample_index = x;
831 return OK;
Andreas Huber20111aa2009-07-14 16:56:47 -0700832 }
James Dongf53263a2010-11-19 18:24:48 -0800833 }
Lajos Molnar599950e2014-07-17 10:52:36 -0700834
Hong Teng8d0dd8b2011-12-15 16:56:49 -0800835 if (left == mNumSyncSamples) {
836 if (flags == kFlagAfter) {
Steve Block29357bc2012-01-06 19:20:56 +0000837 ALOGE("tried to find a sync frame after the last one: %d", left);
Hong Teng8d0dd8b2011-12-15 16:56:49 -0800838 return ERROR_OUT_OF_RANGE;
839 }
Lajos Molnar599950e2014-07-17 10:52:36 -0700840 flags = kFlagBefore;
841 }
842 else if (left == 0) {
843 if (flags == kFlagBefore) {
844 ALOGE("tried to find a sync frame before the first one: %d", left);
845
846 // normally we should return out of range, but that is
847 // treated as end-of-stream. instead seek to first sync
848 //
849 // return ERROR_OUT_OF_RANGE;
850 }
851 flags = kFlagAfter;
Hong Teng8d0dd8b2011-12-15 16:56:49 -0800852 }
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700853
Lajos Molnar599950e2014-07-17 10:52:36 -0700854 // Now ssi[left - 1] <(=) start_sample_index <= ssi[left]
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700855 switch (flags) {
856 case kFlagBefore:
857 {
Lajos Molnar599950e2014-07-17 10:52:36 -0700858 --left;
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700859 break;
860 }
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700861 case kFlagAfter:
862 {
Lajos Molnar599950e2014-07-17 10:52:36 -0700863 // nothing to do
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700864 break;
865 }
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700866 default:
Lajos Molnar599950e2014-07-17 10:52:36 -0700867 {
868 // this route is not used, but implement it nonetheless
869 CHECK(flags == kFlagClosest);
870
871 status_t err = mSampleIterator->seekTo(start_sample_index);
872 if (err != OK) {
873 return err;
874 }
wuhuang12de2b92019-01-18 17:14:03 +0800875 uint64_t sample_time = mSampleIterator->getSampleTime();
Lajos Molnar599950e2014-07-17 10:52:36 -0700876
877 err = mSampleIterator->seekTo(mSyncSamples[left]);
878 if (err != OK) {
879 return err;
880 }
wuhuang12de2b92019-01-18 17:14:03 +0800881 uint64_t upper_time = mSampleIterator->getSampleTime();
Lajos Molnar599950e2014-07-17 10:52:36 -0700882
883 err = mSampleIterator->seekTo(mSyncSamples[left - 1]);
884 if (err != OK) {
885 return err;
886 }
wuhuang12de2b92019-01-18 17:14:03 +0800887 uint64_t lower_time = mSampleIterator->getSampleTime();
Lajos Molnar599950e2014-07-17 10:52:36 -0700888
889 // use abs_difference for safety
890 if (abs_difference(upper_time, sample_time) >
891 abs_difference(sample_time, lower_time)) {
892 --left;
893 }
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700894 break;
Lajos Molnar599950e2014-07-17 10:52:36 -0700895 }
Andreas Huberabd1f4f2010-07-20 15:04:28 -0700896 }
897
Lajos Molnar599950e2014-07-17 10:52:36 -0700898 *sample_index = mSyncSamples[left];
Andreas Huber20111aa2009-07-14 16:56:47 -0700899 return OK;
900}
901
Andreas Huber7e04dcf2009-10-22 13:49:30 -0700902status_t SampleTable::findThumbnailSample(uint32_t *sample_index) {
Andreas Huberc57b6792010-01-19 10:39:21 -0800903 Mutex::Autolock autoLock(mLock);
904
Andreas Huber7e04dcf2009-10-22 13:49:30 -0700905 if (mSyncSampleOffset < 0) {
906 // All samples are sync-samples.
907 *sample_index = 0;
908 return OK;
909 }
910
911 uint32_t bestSampleIndex = 0;
912 size_t maxSampleSize = 0;
913
914 static const size_t kMaxNumSyncSamplesToScan = 20;
915
916 // Consider the first kMaxNumSyncSamplesToScan sync samples and
917 // pick the one with the largest (compressed) size as the thumbnail.
918
919 size_t numSamplesToScan = mNumSyncSamples;
920 if (numSamplesToScan > kMaxNumSyncSamplesToScan) {
921 numSamplesToScan = kMaxNumSyncSamplesToScan;
922 }
923
924 for (size_t i = 0; i < numSamplesToScan; ++i) {
Andreas Huber8bf59e72010-08-06 14:13:10 -0700925 uint32_t x = mSyncSamples[i];
Andreas Huber7e04dcf2009-10-22 13:49:30 -0700926
927 // Now x is a sample index.
928 size_t sampleSize;
Andreas Huberc57b6792010-01-19 10:39:21 -0800929 status_t err = getSampleSize_l(x, &sampleSize);
Andreas Huber7e04dcf2009-10-22 13:49:30 -0700930 if (err != OK) {
931 return err;
932 }
933
934 if (i == 0 || sampleSize > maxSampleSize) {
935 bestSampleIndex = x;
936 maxSampleSize = sampleSize;
937 }
938 }
939
940 *sample_index = bestSampleIndex;
941
942 return OK;
943}
944
Andreas Huberc57b6792010-01-19 10:39:21 -0800945status_t SampleTable::getSampleSize_l(
946 uint32_t sampleIndex, size_t *sampleSize) {
947 return mSampleIterator->getSampleSizeDirect(
948 sampleIndex, sampleSize);
949}
950
zhongli.wangae7f7402014-06-12 14:30:31 +0200951uint32_t SampleTable::getLastSampleIndexInChunk() {
952 Mutex::Autolock autoLock(mLock);
953 return mSampleIterator->getLastSampleIndexInChunk();
954}
955
Andreas Huberc57b6792010-01-19 10:39:21 -0800956status_t SampleTable::getMetaDataForSample(
957 uint32_t sampleIndex,
James Dongc7fc37a2010-11-16 14:04:54 -0800958 off64_t *offset,
Andreas Huberc57b6792010-01-19 10:39:21 -0800959 size_t *size,
wuhuang12de2b92019-01-18 17:14:03 +0800960 uint64_t *compositionTime,
Robert Shih17005652014-04-10 17:30:21 -0700961 bool *isSyncSample,
wuhuang12de2b92019-01-18 17:14:03 +0800962 uint64_t *sampleDuration) {
Andreas Huberc57b6792010-01-19 10:39:21 -0800963 Mutex::Autolock autoLock(mLock);
964
965 status_t err;
966 if ((err = mSampleIterator->seekTo(sampleIndex)) != OK) {
967 return err;
968 }
969
970 if (offset) {
971 *offset = mSampleIterator->getSampleOffset();
972 }
973
974 if (size) {
975 *size = mSampleIterator->getSampleSize();
976 }
977
Andreas Huber4678a6d2011-04-15 11:52:29 -0700978 if (compositionTime) {
979 *compositionTime = mSampleIterator->getSampleTime();
Andreas Huberc57b6792010-01-19 10:39:21 -0800980 }
981
Andreas Huber8bf59e72010-08-06 14:13:10 -0700982 if (isSyncSample) {
983 *isSyncSample = false;
984 if (mSyncSampleOffset < 0) {
985 // Every sample is a sync sample.
986 *isSyncSample = true;
987 } else {
988 size_t i = (mLastSyncSampleIndex < mNumSyncSamples)
989 && (mSyncSamples[mLastSyncSampleIndex] <= sampleIndex)
990 ? mLastSyncSampleIndex : 0;
991
992 while (i < mNumSyncSamples && mSyncSamples[i] < sampleIndex) {
993 ++i;
994 }
995
996 if (i < mNumSyncSamples && mSyncSamples[i] == sampleIndex) {
997 *isSyncSample = true;
998 }
999
1000 mLastSyncSampleIndex = i;
1001 }
1002 }
1003
Robert Shih17005652014-04-10 17:30:21 -07001004 if (sampleDuration) {
1005 *sampleDuration = mSampleIterator->getSampleDuration();
1006 }
1007
Andreas Huberc57b6792010-01-19 10:39:21 -08001008 return OK;
1009}
1010
Marco Nelissenb1dc9e02016-02-17 10:37:29 -08001011int32_t SampleTable::getCompositionTimeOffset(uint32_t sampleIndex) {
Andreas Huber89aa8fe2011-09-19 12:18:47 -07001012 return mCompositionDeltaLookup->getCompositionTimeOffset(sampleIndex);
Andreas Huber4931bb52011-02-03 13:18:16 -08001013}
1014
Andreas Huber20111aa2009-07-14 16:56:47 -07001015} // namespace android