SampleTable.cpp revision 693d271e62a3726689ff68f4505ba49228eb94b2
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(const sp<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