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_NDEBUG 0 18 #define LOG_TAG "OggExtractor" 19 #include <utils/Log.h> 20 21 #include "include/OggExtractor.h" 22 23 #include <cutils/properties.h> 24 #include <media/stagefright/foundation/ABuffer.h> 25 #include <media/stagefright/foundation/ADebug.h> 26 #include <media/stagefright/DataSource.h> 27 #include <media/stagefright/MediaBuffer.h> 28 #include <media/stagefright/MediaBufferGroup.h> 29 #include <media/stagefright/MediaDefs.h> 30 #include <media/stagefright/MediaErrors.h> 31 #include <media/stagefright/MediaSource.h> 32 #include <media/stagefright/MetaData.h> 33 #include <media/stagefright/Utils.h> 34 #include <utils/String8.h> 35 36 extern "C" { 37 #include <Tremolo/codec_internal.h> 38 39 int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb); 40 int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb); 41 int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb); 42 long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op); 43 } 44 45 namespace android { 46 47 struct OggSource : public MediaSource { 48 OggSource(const sp<OggExtractor> &extractor); 49 50 virtual sp<MetaData> getFormat(); 51 52 virtual status_t start(MetaData *params = NULL); 53 virtual status_t stop(); 54 55 virtual status_t read( 56 MediaBuffer **buffer, const ReadOptions *options = NULL); 57 58 protected: 59 virtual ~OggSource(); 60 61 private: 62 sp<OggExtractor> mExtractor; 63 bool mStarted; 64 65 OggSource(const OggSource &); 66 OggSource &operator=(const OggSource &); 67 }; 68 69 struct MyOggExtractor { 70 MyOggExtractor( 71 const sp<DataSource> &source, 72 const char *mimeType, 73 size_t numHeaders, 74 int64_t seekPreRollUs); 75 virtual ~MyOggExtractor(); 76 77 sp<MetaData> getFormat() const; 78 79 // Returns an approximate bitrate in bits per second. 80 virtual uint64_t approxBitrate() const = 0; 81 82 status_t seekToTime(int64_t timeUs); 83 status_t seekToOffset(off64_t offset); 84 virtual status_t readNextPacket(MediaBuffer **buffer) = 0; 85 86 status_t init(); 87 88 sp<MetaData> getFileMetaData() { return mFileMeta; } 89 90 protected: 91 struct Page { 92 uint64_t mGranulePosition; 93 int32_t mPrevPacketSize; 94 uint64_t mPrevPacketPos; 95 uint32_t mSerialNo; 96 uint32_t mPageNo; 97 uint8_t mFlags; 98 uint8_t mNumSegments; 99 uint8_t mLace[255]; 100 }; 101 102 struct TOCEntry { 103 off64_t mPageOffset; 104 int64_t mTimeUs; 105 }; 106 107 sp<DataSource> mSource; 108 off64_t mOffset; 109 Page mCurrentPage; 110 uint64_t mCurGranulePosition; 111 uint64_t mPrevGranulePosition; 112 size_t mCurrentPageSize; 113 bool mFirstPacketInPage; 114 uint64_t mCurrentPageSamples; 115 size_t mNextLaceIndex; 116 117 const char *mMimeType; 118 size_t mNumHeaders; 119 int64_t mSeekPreRollUs; 120 121 off64_t mFirstDataOffset; 122 123 vorbis_info mVi; 124 vorbis_comment mVc; 125 126 sp<MetaData> mMeta; 127 sp<MetaData> mFileMeta; 128 129 Vector<TOCEntry> mTableOfContents; 130 131 ssize_t readPage(off64_t offset, Page *page); 132 status_t findNextPage(off64_t startOffset, off64_t *pageOffset); 133 134 virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const = 0; 135 136 // Extract codec format, metadata tags, and various codec specific data; 137 // the format and CSD's are required to setup the decoders for the enclosed media content. 138 // 139 // Valid values for `type` are: 140 // 1 - bitstream identification header 141 // 3 - comment header 142 // 5 - codec setup header (Vorbis only) 143 virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type) = 0; 144 145 // Read the next ogg packet from the underlying data source; optionally 146 // calculate the timestamp for the output packet whilst pretending 147 // that we are parsing an Ogg Vorbis stream. 148 // 149 // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated; 150 // clients are responsible for releasing the original buffer. 151 status_t _readNextPacket(MediaBuffer **buffer, bool calcVorbisTimestamp); 152 153 int32_t getPacketBlockSize(MediaBuffer *buffer); 154 155 void parseFileMetaData(); 156 157 status_t findPrevGranulePosition(off64_t pageOffset, uint64_t *granulePos); 158 159 void buildTableOfContents(); 160 161 MyOggExtractor(const MyOggExtractor &); 162 MyOggExtractor &operator=(const MyOggExtractor &); 163 }; 164 165 struct MyVorbisExtractor : public MyOggExtractor { 166 MyVorbisExtractor(const sp<DataSource> &source) 167 : MyOggExtractor(source, 168 MEDIA_MIMETYPE_AUDIO_VORBIS, 169 /* numHeaders */ 3, 170 /* seekPreRollUs */ 0) { 171 } 172 173 virtual uint64_t approxBitrate() const; 174 175 virtual status_t readNextPacket(MediaBuffer **buffer) { 176 return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true); 177 } 178 179 protected: 180 virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const { 181 return granulePos * 1000000ll / mVi.rate; 182 } 183 184 virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type); 185 }; 186 187 struct MyOpusExtractor : public MyOggExtractor { 188 static const int32_t kOpusSampleRate = 48000; 189 static const int64_t kOpusSeekPreRollUs = 80000; // 80 ms 190 191 MyOpusExtractor(const sp<DataSource> &source) 192 : MyOggExtractor(source, MEDIA_MIMETYPE_AUDIO_OPUS, /*numHeaders*/ 2, kOpusSeekPreRollUs), 193 mChannelCount(0), 194 mCodecDelay(0), 195 mStartGranulePosition(-1) { 196 } 197 198 virtual uint64_t approxBitrate() const { 199 return 0; 200 } 201 202 virtual status_t readNextPacket(MediaBuffer **buffer); 203 204 protected: 205 virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; 206 virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type); 207 208 private: 209 status_t verifyOpusHeader(MediaBuffer *buffer); 210 status_t verifyOpusComments(MediaBuffer *buffer); 211 uint32_t getNumSamplesInPacket(MediaBuffer *buffer) const; 212 213 uint8_t mChannelCount; 214 uint16_t mCodecDelay; 215 int64_t mStartGranulePosition; 216 }; 217 218 static void extractAlbumArt( 219 const sp<MetaData> &fileMeta, const void *data, size_t size); 220 221 //////////////////////////////////////////////////////////////////////////////// 222 223 OggSource::OggSource(const sp<OggExtractor> &extractor) 224 : mExtractor(extractor), 225 mStarted(false) { 226 } 227 228 OggSource::~OggSource() { 229 if (mStarted) { 230 stop(); 231 } 232 } 233 234 sp<MetaData> OggSource::getFormat() { 235 return mExtractor->mImpl->getFormat(); 236 } 237 238 status_t OggSource::start(MetaData * /* params */) { 239 if (mStarted) { 240 return INVALID_OPERATION; 241 } 242 243 mStarted = true; 244 245 return OK; 246 } 247 248 status_t OggSource::stop() { 249 mStarted = false; 250 251 return OK; 252 } 253 254 status_t OggSource::read( 255 MediaBuffer **out, const ReadOptions *options) { 256 *out = NULL; 257 258 int64_t seekTimeUs; 259 ReadOptions::SeekMode mode; 260 if (options && options->getSeekTo(&seekTimeUs, &mode)) { 261 status_t err = mExtractor->mImpl->seekToTime(seekTimeUs); 262 if (err != OK) { 263 return err; 264 } 265 } 266 267 MediaBuffer *packet; 268 status_t err = mExtractor->mImpl->readNextPacket(&packet); 269 270 if (err != OK) { 271 return err; 272 } 273 274 #if 0 275 int64_t timeUs; 276 if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 277 ALOGI("found time = %lld us", timeUs); 278 } else { 279 ALOGI("NO time"); 280 } 281 #endif 282 283 packet->meta_data()->setInt32(kKeyIsSyncFrame, 1); 284 285 *out = packet; 286 287 return OK; 288 } 289 290 //////////////////////////////////////////////////////////////////////////////// 291 292 MyOggExtractor::MyOggExtractor( 293 const sp<DataSource> &source, 294 const char *mimeType, 295 size_t numHeaders, 296 int64_t seekPreRollUs) 297 : mSource(source), 298 mOffset(0), 299 mCurGranulePosition(0), 300 mPrevGranulePosition(0), 301 mCurrentPageSize(0), 302 mFirstPacketInPage(true), 303 mCurrentPageSamples(0), 304 mNextLaceIndex(0), 305 mMimeType(mimeType), 306 mNumHeaders(numHeaders), 307 mSeekPreRollUs(seekPreRollUs), 308 mFirstDataOffset(-1) { 309 mCurrentPage.mNumSegments = 0; 310 311 vorbis_info_init(&mVi); 312 vorbis_comment_init(&mVc); 313 } 314 315 MyOggExtractor::~MyOggExtractor() { 316 vorbis_comment_clear(&mVc); 317 vorbis_info_clear(&mVi); 318 } 319 320 sp<MetaData> MyOggExtractor::getFormat() const { 321 return mMeta; 322 } 323 324 status_t MyOggExtractor::findNextPage( 325 off64_t startOffset, off64_t *pageOffset) { 326 *pageOffset = startOffset; 327 328 for (;;) { 329 char signature[4]; 330 ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 331 332 if (n < 4) { 333 *pageOffset = 0; 334 335 return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 336 } 337 338 if (!memcmp(signature, "OggS", 4)) { 339 if (*pageOffset > startOffset) { 340 ALOGV("skipped %lld bytes of junk to reach next frame", 341 (long long)(*pageOffset - startOffset)); 342 } 343 344 return OK; 345 } 346 347 ++*pageOffset; 348 } 349 } 350 351 // Given the offset of the "current" page, find the page immediately preceding 352 // it (if any) and return its granule position. 353 // To do this we back up from the "current" page's offset until we find any 354 // page preceding it and then scan forward to just before the current page. 355 status_t MyOggExtractor::findPrevGranulePosition( 356 off64_t pageOffset, uint64_t *granulePos) { 357 *granulePos = 0; 358 359 off64_t prevPageOffset = 0; 360 off64_t prevGuess = pageOffset; 361 for (;;) { 362 if (prevGuess >= 5000) { 363 prevGuess -= 5000; 364 } else { 365 prevGuess = 0; 366 } 367 368 ALOGV("backing up %lld bytes", (long long)(pageOffset - prevGuess)); 369 370 status_t err = findNextPage(prevGuess, &prevPageOffset); 371 if (err == ERROR_END_OF_STREAM) { 372 // We are at the last page and didn't back off enough; 373 // back off 5000 bytes more and try again. 374 continue; 375 } else if (err != OK) { 376 return err; 377 } 378 379 if (prevPageOffset < pageOffset || prevGuess == 0) { 380 break; 381 } 382 } 383 384 if (prevPageOffset == pageOffset) { 385 // We did not find a page preceding this one. 386 return UNKNOWN_ERROR; 387 } 388 389 ALOGV("prevPageOffset at %lld, pageOffset at %lld", 390 (long long)prevPageOffset, (long long)pageOffset); 391 392 for (;;) { 393 Page prevPage; 394 ssize_t n = readPage(prevPageOffset, &prevPage); 395 396 if (n <= 0) { 397 return (status_t)n; 398 } 399 400 prevPageOffset += n; 401 402 if (prevPageOffset == pageOffset) { 403 *granulePos = prevPage.mGranulePosition; 404 return OK; 405 } 406 } 407 } 408 409 status_t MyOggExtractor::seekToTime(int64_t timeUs) { 410 timeUs -= mSeekPreRollUs; 411 if (timeUs < 0) { 412 timeUs = 0; 413 } 414 415 if (mTableOfContents.isEmpty()) { 416 // Perform approximate seeking based on avg. bitrate. 417 uint64_t bps = approxBitrate(); 418 if (bps <= 0) { 419 return INVALID_OPERATION; 420 } 421 422 off64_t pos = timeUs * bps / 8000000ll; 423 424 ALOGV("seeking to offset %lld", (long long)pos); 425 return seekToOffset(pos); 426 } 427 428 size_t left = 0; 429 size_t right_plus_one = mTableOfContents.size(); 430 while (left < right_plus_one) { 431 size_t center = left + (right_plus_one - left) / 2; 432 433 const TOCEntry &entry = mTableOfContents.itemAt(center); 434 435 if (timeUs < entry.mTimeUs) { 436 right_plus_one = center; 437 } else if (timeUs > entry.mTimeUs) { 438 left = center + 1; 439 } else { 440 left = center; 441 break; 442 } 443 } 444 445 if (left == mTableOfContents.size()) { 446 --left; 447 } 448 449 const TOCEntry &entry = mTableOfContents.itemAt(left); 450 451 ALOGV("seeking to entry %zu / %zu at offset %lld", 452 left, mTableOfContents.size(), (long long)entry.mPageOffset); 453 454 return seekToOffset(entry.mPageOffset); 455 } 456 457 status_t MyOggExtractor::seekToOffset(off64_t offset) { 458 if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 459 // Once we know where the actual audio data starts (past the headers) 460 // don't ever seek to anywhere before that. 461 offset = mFirstDataOffset; 462 } 463 464 off64_t pageOffset; 465 status_t err = findNextPage(offset, &pageOffset); 466 467 if (err != OK) { 468 return err; 469 } 470 471 // We found the page we wanted to seek to, but we'll also need 472 // the page preceding it to determine how many valid samples are on 473 // this page. 474 findPrevGranulePosition(pageOffset, &mPrevGranulePosition); 475 476 mOffset = pageOffset; 477 478 mCurrentPageSize = 0; 479 mFirstPacketInPage = true; 480 mCurrentPageSamples = 0; 481 mCurrentPage.mNumSegments = 0; 482 mCurrentPage.mPrevPacketSize = -1; 483 mNextLaceIndex = 0; 484 485 // XXX what if new page continues packet from last??? 486 487 return OK; 488 } 489 490 ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { 491 uint8_t header[27]; 492 ssize_t n; 493 if ((n = mSource->readAt(offset, header, sizeof(header))) 494 < (ssize_t)sizeof(header)) { 495 ALOGV("failed to read %zu bytes at offset %#016llx, got %zd bytes", 496 sizeof(header), (long long)offset, n); 497 498 if (n < 0) { 499 return n; 500 } else if (n == 0) { 501 return ERROR_END_OF_STREAM; 502 } else { 503 return ERROR_IO; 504 } 505 } 506 507 if (memcmp(header, "OggS", 4)) { 508 return ERROR_MALFORMED; 509 } 510 511 if (header[4] != 0) { 512 // Wrong version. 513 514 return ERROR_UNSUPPORTED; 515 } 516 517 page->mFlags = header[5]; 518 519 if (page->mFlags & ~7) { 520 // Only bits 0-2 are defined in version 0. 521 return ERROR_MALFORMED; 522 } 523 524 page->mGranulePosition = U64LE_AT(&header[6]); 525 526 #if 0 527 printf("granulePosition = %llu (0x%llx)\n", 528 page->mGranulePosition, page->mGranulePosition); 529 #endif 530 531 page->mSerialNo = U32LE_AT(&header[14]); 532 page->mPageNo = U32LE_AT(&header[18]); 533 534 page->mNumSegments = header[26]; 535 if (mSource->readAt( 536 offset + sizeof(header), page->mLace, page->mNumSegments) 537 < (ssize_t)page->mNumSegments) { 538 return ERROR_IO; 539 } 540 541 size_t totalSize = 0;; 542 for (size_t i = 0; i < page->mNumSegments; ++i) { 543 totalSize += page->mLace[i]; 544 } 545 546 #if 0 547 String8 tmp; 548 for (size_t i = 0; i < page->mNumSegments; ++i) { 549 char x[32]; 550 sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 551 552 tmp.append(x); 553 } 554 555 ALOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 556 #endif 557 558 return sizeof(header) + page->mNumSegments + totalSize; 559 } 560 561 status_t MyOpusExtractor::readNextPacket(MediaBuffer **out) { 562 if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) { 563 // The first sample might not start at time 0; find out where by subtracting 564 // the number of samples on the first page from the granule position 565 // (position of last complete sample) of the first page. This happens 566 // the first time before we attempt to read a packet from the first page. 567 MediaBuffer *mBuf; 568 uint32_t numSamples = 0; 569 uint64_t curGranulePosition = 0; 570 while (true) { 571 status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false); 572 if (err != OK && err != ERROR_END_OF_STREAM) { 573 return err; 574 } 575 // First two pages are header pages. 576 if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) { 577 break; 578 } 579 curGranulePosition = mCurrentPage.mGranulePosition; 580 numSamples += getNumSamplesInPacket(mBuf); 581 mBuf->release(); 582 mBuf = NULL; 583 } 584 585 if (curGranulePosition > numSamples) { 586 mStartGranulePosition = curGranulePosition - numSamples; 587 } else { 588 mStartGranulePosition = 0; 589 } 590 seekToOffset(0); 591 } 592 593 status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false); 594 if (err != OK) { 595 return err; 596 } 597 598 int32_t currentPageSamples; 599 // Calculate timestamps by accumulating durations starting from the first sample of a page; 600 // We assume that we only seek to page boundaries. 601 if ((*out)->meta_data()->findInt32(kKeyValidSamples, ¤tPageSamples)) { 602 // first packet in page 603 if (mOffset == mFirstDataOffset) { 604 currentPageSamples -= mStartGranulePosition; 605 (*out)->meta_data()->setInt32(kKeyValidSamples, currentPageSamples); 606 } 607 mCurGranulePosition = mCurrentPage.mGranulePosition - currentPageSamples; 608 } 609 610 int64_t timeUs = getTimeUsOfGranule(mCurGranulePosition); 611 (*out)->meta_data()->setInt64(kKeyTime, timeUs); 612 613 uint32_t frames = getNumSamplesInPacket(*out); 614 mCurGranulePosition += frames; 615 return OK; 616 } 617 618 uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBuffer *buffer) const { 619 if (buffer == NULL || buffer->range_length() < 1) { 620 return 0; 621 } 622 623 uint8_t *data = (uint8_t *)buffer->data() + buffer->range_offset(); 624 uint8_t toc = data[0]; 625 uint8_t config = (toc >> 3) & 0x1f; 626 uint32_t frameSizesUs[] = { 627 10000, 20000, 40000, 60000, // 0...3 628 10000, 20000, 40000, 60000, // 4...7 629 10000, 20000, 40000, 60000, // 8...11 630 10000, 20000, // 12...13 631 10000, 20000, // 14...15 632 2500, 5000, 10000, 20000, // 16...19 633 2500, 5000, 10000, 20000, // 20...23 634 2500, 5000, 10000, 20000, // 24...27 635 2500, 5000, 10000, 20000 // 28...31 636 }; 637 uint32_t frameSizeUs = frameSizesUs[config]; 638 639 uint32_t numFrames; 640 uint8_t c = toc & 3; 641 switch (c) { 642 case 0: 643 numFrames = 1; 644 break; 645 case 1: 646 case 2: 647 numFrames = 2; 648 break; 649 case 3: 650 if (buffer->range_length() < 3) { 651 numFrames = 0; 652 } else { 653 numFrames = data[2] & 0x3f; 654 } 655 break; 656 default: 657 TRESPASS(); 658 } 659 660 uint32_t numSamples = frameSizeUs * numFrames * kOpusSampleRate / 1000000; 661 return numSamples; 662 } 663 664 status_t MyOggExtractor::_readNextPacket(MediaBuffer **out, bool calcVorbisTimestamp) { 665 *out = NULL; 666 667 MediaBuffer *buffer = NULL; 668 int64_t timeUs = -1; 669 670 for (;;) { 671 size_t i; 672 size_t packetSize = 0; 673 bool gotFullPacket = false; 674 for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 675 uint8_t lace = mCurrentPage.mLace[i]; 676 677 packetSize += lace; 678 679 if (lace < 255) { 680 gotFullPacket = true; 681 ++i; 682 break; 683 } 684 } 685 686 if (mNextLaceIndex < mCurrentPage.mNumSegments) { 687 off64_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 688 for (size_t j = 0; j < mNextLaceIndex; ++j) { 689 dataOffset += mCurrentPage.mLace[j]; 690 } 691 692 size_t fullSize = packetSize; 693 if (buffer != NULL) { 694 fullSize += buffer->range_length(); 695 } 696 MediaBuffer *tmp = new MediaBuffer(fullSize); 697 if (buffer != NULL) { 698 memcpy(tmp->data(), buffer->data(), buffer->range_length()); 699 tmp->set_range(0, buffer->range_length()); 700 buffer->release(); 701 } else { 702 tmp->set_range(0, 0); 703 } 704 buffer = tmp; 705 706 ssize_t n = mSource->readAt( 707 dataOffset, 708 (uint8_t *)buffer->data() + buffer->range_length(), 709 packetSize); 710 711 if (n < (ssize_t)packetSize) { 712 ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes", 713 packetSize, (long long)dataOffset, n); 714 return ERROR_IO; 715 } 716 717 buffer->set_range(0, fullSize); 718 719 mNextLaceIndex = i; 720 721 if (gotFullPacket) { 722 // We've just read the entire packet. 723 724 if (mFirstPacketInPage) { 725 buffer->meta_data()->setInt32( 726 kKeyValidSamples, mCurrentPageSamples); 727 mFirstPacketInPage = false; 728 } 729 730 if (calcVorbisTimestamp) { 731 int32_t curBlockSize = getPacketBlockSize(buffer); 732 if (mCurrentPage.mPrevPacketSize < 0) { 733 mCurrentPage.mPrevPacketSize = curBlockSize; 734 mCurrentPage.mPrevPacketPos = 735 mCurrentPage.mGranulePosition - mCurrentPageSamples; 736 timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate; 737 } else { 738 // The effective block size is the average of the two overlapped blocks 739 int32_t actualBlockSize = 740 (curBlockSize + mCurrentPage.mPrevPacketSize) / 2; 741 timeUs = mCurrentPage.mPrevPacketPos * 1000000ll / mVi.rate; 742 // The actual size output by the decoder will be half the effective 743 // size, due to the overlap 744 mCurrentPage.mPrevPacketPos += actualBlockSize / 2; 745 mCurrentPage.mPrevPacketSize = curBlockSize; 746 } 747 buffer->meta_data()->setInt64(kKeyTime, timeUs); 748 } 749 *out = buffer; 750 751 return OK; 752 } 753 754 // fall through, the buffer now contains the start of the packet. 755 } 756 757 CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 758 759 mOffset += mCurrentPageSize; 760 ssize_t n = readPage(mOffset, &mCurrentPage); 761 762 if (n <= 0) { 763 if (buffer) { 764 buffer->release(); 765 buffer = NULL; 766 } 767 768 ALOGV("readPage returned %zd", n); 769 770 return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 771 } 772 773 mCurrentPageSamples = 774 mCurrentPage.mGranulePosition - mPrevGranulePosition; 775 mFirstPacketInPage = true; 776 777 mPrevGranulePosition = mCurrentPage.mGranulePosition; 778 779 mCurrentPageSize = n; 780 mNextLaceIndex = 0; 781 782 if (buffer != NULL) { 783 if ((mCurrentPage.mFlags & 1) == 0) { 784 // This page does not continue the packet, i.e. the packet 785 // is already complete. 786 787 if (timeUs >= 0) { 788 buffer->meta_data()->setInt64(kKeyTime, timeUs); 789 } 790 791 buffer->meta_data()->setInt32( 792 kKeyValidSamples, mCurrentPageSamples); 793 mFirstPacketInPage = false; 794 795 *out = buffer; 796 797 return OK; 798 } 799 } 800 } 801 } 802 803 status_t MyOggExtractor::init() { 804 mMeta = new MetaData; 805 mMeta->setCString(kKeyMIMEType, mMimeType); 806 807 status_t err; 808 MediaBuffer *packet; 809 for (size_t i = 0; i < mNumHeaders; ++i) { 810 // ignore timestamp for configuration packets 811 if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) { 812 return err; 813 } 814 ALOGV("read packet of size %zu\n", packet->range_length()); 815 err = verifyHeader(packet, /* type = */ i * 2 + 1); 816 packet->release(); 817 packet = NULL; 818 if (err != OK) { 819 return err; 820 } 821 } 822 823 mFirstDataOffset = mOffset + mCurrentPageSize; 824 825 off64_t size; 826 uint64_t lastGranulePosition; 827 if (!(mSource->flags() & DataSource::kIsCachingDataSource) 828 && mSource->getSize(&size) == OK 829 && findPrevGranulePosition(size, &lastGranulePosition) == OK) { 830 // Let's assume it's cheap to seek to the end. 831 // The granule position of the final page in the stream will 832 // give us the exact duration of the content, something that 833 // we can only approximate using avg. bitrate if seeking to 834 // the end is too expensive or impossible (live streaming). 835 836 int64_t durationUs = getTimeUsOfGranule(lastGranulePosition); 837 838 mMeta->setInt64(kKeyDuration, durationUs); 839 840 buildTableOfContents(); 841 } 842 843 return OK; 844 } 845 846 void MyOggExtractor::buildTableOfContents() { 847 off64_t offset = mFirstDataOffset; 848 Page page; 849 ssize_t pageSize; 850 while ((pageSize = readPage(offset, &page)) > 0) { 851 mTableOfContents.push(); 852 853 TOCEntry &entry = 854 mTableOfContents.editItemAt(mTableOfContents.size() - 1); 855 856 entry.mPageOffset = offset; 857 entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition); 858 859 offset += (size_t)pageSize; 860 } 861 862 // Limit the maximum amount of RAM we spend on the table of contents, 863 // if necessary thin out the table evenly to trim it down to maximum 864 // size. 865 866 static const size_t kMaxTOCSize = 8192; 867 static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry); 868 869 size_t numerator = mTableOfContents.size(); 870 871 if (numerator > kMaxNumTOCEntries) { 872 size_t denom = numerator - kMaxNumTOCEntries; 873 874 size_t accum = 0; 875 for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) { 876 accum += denom; 877 if (accum >= numerator) { 878 mTableOfContents.removeAt(i); 879 accum -= numerator; 880 } 881 } 882 } 883 } 884 885 int32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) { 886 const uint8_t *data = 887 (const uint8_t *)buffer->data() + buffer->range_offset(); 888 889 size_t size = buffer->range_length(); 890 891 ogg_buffer buf; 892 buf.data = (uint8_t *)data; 893 buf.size = size; 894 buf.refcount = 1; 895 buf.ptr.owner = NULL; 896 897 ogg_reference ref; 898 ref.buffer = &buf; 899 ref.begin = 0; 900 ref.length = size; 901 ref.next = NULL; 902 903 ogg_packet pack; 904 pack.packet = &ref; 905 pack.bytes = ref.length; 906 pack.b_o_s = 0; 907 pack.e_o_s = 0; 908 pack.granulepos = 0; 909 pack.packetno = 0; 910 911 return vorbis_packet_blocksize(&mVi, &pack); 912 } 913 914 int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const { 915 uint64_t pcmSamplePosition = 0; 916 if (granulePos > mCodecDelay) { 917 pcmSamplePosition = granulePos - mCodecDelay; 918 } 919 return pcmSamplePosition * 1000000ll / kOpusSampleRate; 920 } 921 922 status_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) { 923 switch (type) { 924 // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean 925 // header and comments such that we can share code with MyVorbisExtractor. 926 case 1: 927 return verifyOpusHeader(buffer); 928 case 3: 929 return verifyOpusComments(buffer); 930 default: 931 return INVALID_OPERATION; 932 } 933 } 934 935 status_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) { 936 const size_t kOpusHeaderSize = 19; 937 const uint8_t *data = 938 (const uint8_t *)buffer->data() + buffer->range_offset(); 939 940 size_t size = buffer->range_length(); 941 942 if (size < kOpusHeaderSize 943 || memcmp(data, "OpusHead", 8) 944 || /* version = */ data[8] != 1) { 945 return ERROR_MALFORMED; 946 } 947 948 mChannelCount = data[9]; 949 mCodecDelay = U16LE_AT(&data[10]); 950 951 mMeta->setData(kKeyOpusHeader, 0, data, size); 952 mMeta->setInt32(kKeySampleRate, kOpusSampleRate); 953 mMeta->setInt32(kKeyChannelCount, mChannelCount); 954 mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/); 955 mMeta->setInt64(kKeyOpusCodecDelay /* ns */, 956 mCodecDelay /* sample/s */ * 1000000000 / kOpusSampleRate); 957 958 return OK; 959 } 960 961 status_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) { 962 // add artificial framing bit so we can reuse _vorbis_unpack_comment 963 int32_t commentSize = buffer->range_length() + 1; 964 sp<ABuffer> aBuf = new ABuffer(commentSize); 965 if (aBuf->capacity() <= buffer->range_length()) { 966 return ERROR_MALFORMED; 967 } 968 969 uint8_t* commentData = aBuf->data(); 970 memcpy(commentData, 971 (uint8_t *)buffer->data() + buffer->range_offset(), 972 buffer->range_length()); 973 974 ogg_buffer buf; 975 buf.data = commentData; 976 buf.size = commentSize; 977 buf.refcount = 1; 978 buf.ptr.owner = NULL; 979 980 ogg_reference ref; 981 ref.buffer = &buf; 982 ref.begin = 0; 983 ref.length = commentSize; 984 ref.next = NULL; 985 986 oggpack_buffer bits; 987 oggpack_readinit(&bits, &ref); 988 989 // skip 'OpusTags' 990 const char *OpusTags = "OpusTags"; 991 const int32_t headerLen = strlen(OpusTags); 992 int32_t framingBitOffset = headerLen; 993 for (int i = 0; i < headerLen; ++i) { 994 char chr = oggpack_read(&bits, 8); 995 if (chr != OpusTags[i]) { 996 return ERROR_MALFORMED; 997 } 998 } 999 1000 int32_t vendorLen = oggpack_read(&bits, 32); 1001 framingBitOffset += 4; 1002 if (vendorLen < 0 || vendorLen > commentSize - 8) { 1003 return ERROR_MALFORMED; 1004 } 1005 // skip vendor string 1006 framingBitOffset += vendorLen; 1007 for (int i = 0; i < vendorLen; ++i) { 1008 oggpack_read(&bits, 8); 1009 } 1010 1011 int32_t n = oggpack_read(&bits, 32); 1012 framingBitOffset += 4; 1013 if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { 1014 return ERROR_MALFORMED; 1015 } 1016 for (int i = 0; i < n; ++i) { 1017 int32_t len = oggpack_read(&bits, 32); 1018 framingBitOffset += 4; 1019 if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { 1020 return ERROR_MALFORMED; 1021 } 1022 framingBitOffset += len; 1023 for (int j = 0; j < len; ++j) { 1024 oggpack_read(&bits, 8); 1025 } 1026 } 1027 if (framingBitOffset < 0 || framingBitOffset >= commentSize) { 1028 return ERROR_MALFORMED; 1029 } 1030 commentData[framingBitOffset] = 1; 1031 1032 buf.data = commentData + headerLen; 1033 buf.size = commentSize - headerLen; 1034 buf.refcount = 1; 1035 buf.ptr.owner = NULL; 1036 1037 ref.buffer = &buf; 1038 ref.begin = 0; 1039 ref.length = commentSize - headerLen; 1040 ref.next = NULL; 1041 1042 oggpack_readinit(&bits, &ref); 1043 int err = _vorbis_unpack_comment(&mVc, &bits); 1044 if (0 != err) { 1045 return ERROR_MALFORMED; 1046 } 1047 1048 parseFileMetaData(); 1049 return OK; 1050 } 1051 1052 status_t MyVorbisExtractor::verifyHeader( 1053 MediaBuffer *buffer, uint8_t type) { 1054 const uint8_t *data = 1055 (const uint8_t *)buffer->data() + buffer->range_offset(); 1056 1057 size_t size = buffer->range_length(); 1058 1059 if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 1060 return ERROR_MALFORMED; 1061 } 1062 1063 ogg_buffer buf; 1064 buf.data = (uint8_t *)data; 1065 buf.size = size; 1066 buf.refcount = 1; 1067 buf.ptr.owner = NULL; 1068 1069 ogg_reference ref; 1070 ref.buffer = &buf; 1071 ref.begin = 0; 1072 ref.length = size; 1073 ref.next = NULL; 1074 1075 oggpack_buffer bits; 1076 oggpack_readinit(&bits, &ref); 1077 1078 if (oggpack_read(&bits, 8) != type) { 1079 return ERROR_MALFORMED; 1080 } 1081 for (size_t i = 0; i < 6; ++i) { 1082 oggpack_read(&bits, 8); // skip 'vorbis' 1083 } 1084 1085 switch (type) { 1086 case 1: 1087 { 1088 if (0 != _vorbis_unpack_info(&mVi, &bits)) { 1089 return ERROR_MALFORMED; 1090 } 1091 1092 mMeta->setData(kKeyVorbisInfo, 0, data, size); 1093 mMeta->setInt32(kKeySampleRate, mVi.rate); 1094 mMeta->setInt32(kKeyChannelCount, mVi.channels); 1095 1096 ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); 1097 ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); 1098 ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 1099 ALOGV("window-bitrate = %ld", mVi.bitrate_window); 1100 ALOGV("blocksizes: %d/%d", 1101 vorbis_info_blocksize(&mVi, 0), 1102 vorbis_info_blocksize(&mVi, 1) 1103 ); 1104 1105 off64_t size; 1106 if (mSource->getSize(&size) == OK) { 1107 uint64_t bps = approxBitrate(); 1108 if (bps != 0) { 1109 mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 1110 } 1111 } 1112 break; 1113 } 1114 1115 case 3: 1116 { 1117 if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 1118 return ERROR_MALFORMED; 1119 } 1120 1121 parseFileMetaData(); 1122 break; 1123 } 1124 1125 case 5: 1126 { 1127 if (0 != _vorbis_unpack_books(&mVi, &bits)) { 1128 return ERROR_MALFORMED; 1129 } 1130 1131 mMeta->setData(kKeyVorbisBooks, 0, data, size); 1132 break; 1133 } 1134 } 1135 1136 return OK; 1137 } 1138 1139 uint64_t MyVorbisExtractor::approxBitrate() const { 1140 if (mVi.bitrate_nominal != 0) { 1141 return mVi.bitrate_nominal; 1142 } 1143 1144 return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 1145 } 1146 1147 void MyOggExtractor::parseFileMetaData() { 1148 mFileMeta = new MetaData; 1149 mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 1150 1151 for (int i = 0; i < mVc.comments; ++i) { 1152 const char *comment = mVc.user_comments[i]; 1153 size_t commentLength = mVc.comment_lengths[i]; 1154 parseVorbisComment(mFileMeta, comment, commentLength); 1155 //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 1156 } 1157 } 1158 1159 void parseVorbisComment( 1160 const sp<MetaData> &fileMeta, const char *comment, size_t commentLength) 1161 { 1162 struct { 1163 const char *const mTag; 1164 uint32_t mKey; 1165 } kMap[] = { 1166 { "TITLE", kKeyTitle }, 1167 { "ARTIST", kKeyArtist }, 1168 { "ALBUMARTIST", kKeyAlbumArtist }, 1169 { "ALBUM ARTIST", kKeyAlbumArtist }, 1170 { "COMPILATION", kKeyCompilation }, 1171 { "ALBUM", kKeyAlbum }, 1172 { "COMPOSER", kKeyComposer }, 1173 { "GENRE", kKeyGenre }, 1174 { "AUTHOR", kKeyAuthor }, 1175 { "TRACKNUMBER", kKeyCDTrackNumber }, 1176 { "DISCNUMBER", kKeyDiscNumber }, 1177 { "DATE", kKeyDate }, 1178 { "YEAR", kKeyYear }, 1179 { "LYRICIST", kKeyWriter }, 1180 { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 1181 { "ANDROID_LOOP", kKeyAutoLoop }, 1182 }; 1183 1184 for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 1185 size_t tagLen = strlen(kMap[j].mTag); 1186 if (!strncasecmp(kMap[j].mTag, comment, tagLen) 1187 && comment[tagLen] == '=') { 1188 if (kMap[j].mKey == kKeyAlbumArt) { 1189 extractAlbumArt( 1190 fileMeta, 1191 &comment[tagLen + 1], 1192 commentLength - tagLen - 1); 1193 } else if (kMap[j].mKey == kKeyAutoLoop) { 1194 if (!strcasecmp(&comment[tagLen + 1], "true")) { 1195 fileMeta->setInt32(kKeyAutoLoop, true); 1196 } 1197 } else { 1198 fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 1199 } 1200 } 1201 } 1202 1203 } 1204 1205 // The returned buffer should be free()d. 1206 static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { 1207 *outSize = 0; 1208 1209 if ((size % 4) != 0) { 1210 return NULL; 1211 } 1212 1213 size_t n = size; 1214 size_t padding = 0; 1215 if (n >= 1 && s[n - 1] == '=') { 1216 padding = 1; 1217 1218 if (n >= 2 && s[n - 2] == '=') { 1219 padding = 2; 1220 } 1221 } 1222 1223 size_t outLen = 3 * size / 4 - padding; 1224 1225 *outSize = outLen; 1226 1227 void *buffer = malloc(outLen); 1228 1229 uint8_t *out = (uint8_t *)buffer; 1230 size_t j = 0; 1231 uint32_t accum = 0; 1232 for (size_t i = 0; i < n; ++i) { 1233 char c = s[i]; 1234 unsigned value; 1235 if (c >= 'A' && c <= 'Z') { 1236 value = c - 'A'; 1237 } else if (c >= 'a' && c <= 'z') { 1238 value = 26 + c - 'a'; 1239 } else if (c >= '0' && c <= '9') { 1240 value = 52 + c - '0'; 1241 } else if (c == '+') { 1242 value = 62; 1243 } else if (c == '/') { 1244 value = 63; 1245 } else if (c != '=') { 1246 return NULL; 1247 } else { 1248 if (i < n - padding) { 1249 return NULL; 1250 } 1251 1252 value = 0; 1253 } 1254 1255 accum = (accum << 6) | value; 1256 1257 if (((i + 1) % 4) == 0) { 1258 out[j++] = (accum >> 16); 1259 1260 if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 1261 if (j < outLen) { out[j++] = accum & 0xff; } 1262 1263 accum = 0; 1264 } 1265 } 1266 1267 return (uint8_t *)buffer; 1268 } 1269 1270 static void extractAlbumArt( 1271 const sp<MetaData> &fileMeta, const void *data, size_t size) { 1272 ALOGV("extractAlbumArt from '%s'", (const char *)data); 1273 1274 size_t flacSize; 1275 uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); 1276 1277 if (flac == NULL) { 1278 ALOGE("malformed base64 encoded data."); 1279 return; 1280 } 1281 1282 ALOGV("got flac of size %zu", flacSize); 1283 1284 uint32_t picType; 1285 uint32_t typeLen; 1286 uint32_t descLen; 1287 uint32_t dataLen; 1288 char type[128]; 1289 1290 if (flacSize < 8) { 1291 goto exit; 1292 } 1293 1294 picType = U32_AT(flac); 1295 1296 if (picType != 3) { 1297 // This is not a front cover. 1298 goto exit; 1299 } 1300 1301 typeLen = U32_AT(&flac[4]); 1302 if (typeLen > sizeof(type) - 1) { 1303 goto exit; 1304 } 1305 1306 // we've already checked above that flacSize >= 8 1307 if (flacSize - 8 < typeLen) { 1308 goto exit; 1309 } 1310 1311 memcpy(type, &flac[8], typeLen); 1312 type[typeLen] = '\0'; 1313 1314 ALOGV("picType = %d, type = '%s'", picType, type); 1315 1316 if (!strcmp(type, "-->")) { 1317 // This is not inline cover art, but an external url instead. 1318 goto exit; 1319 } 1320 1321 descLen = U32_AT(&flac[8 + typeLen]); 1322 1323 if (flacSize < 32 || 1324 flacSize - 32 < typeLen || 1325 flacSize - 32 - typeLen < descLen) { 1326 goto exit; 1327 } 1328 1329 dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 1330 1331 1332 // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0 1333 if (flacSize - 32 - typeLen - descLen < dataLen) { 1334 goto exit; 1335 } 1336 1337 ALOGV("got image data, %zu trailing bytes", 1338 flacSize - 32 - typeLen - descLen - dataLen); 1339 1340 fileMeta->setData( 1341 kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 1342 1343 fileMeta->setCString(kKeyAlbumArtMIME, type); 1344 1345 exit: 1346 free(flac); 1347 flac = NULL; 1348 } 1349 1350 //////////////////////////////////////////////////////////////////////////////// 1351 1352 OggExtractor::OggExtractor(const sp<DataSource> &source) 1353 : mDataSource(source), 1354 mInitCheck(NO_INIT), 1355 mImpl(NULL) { 1356 for (int i = 0; i < 2; ++i) { 1357 if (mImpl != NULL) { 1358 delete mImpl; 1359 } 1360 if (i == 0) { 1361 mImpl = new MyVorbisExtractor(mDataSource); 1362 } else { 1363 mImpl = new MyOpusExtractor(mDataSource); 1364 } 1365 mInitCheck = mImpl->seekToOffset(0); 1366 1367 if (mInitCheck == OK) { 1368 mInitCheck = mImpl->init(); 1369 if (mInitCheck == OK) { 1370 break; 1371 } 1372 } 1373 } 1374 } 1375 1376 OggExtractor::~OggExtractor() { 1377 delete mImpl; 1378 mImpl = NULL; 1379 } 1380 1381 size_t OggExtractor::countTracks() { 1382 return mInitCheck != OK ? 0 : 1; 1383 } 1384 1385 sp<MediaSource> OggExtractor::getTrack(size_t index) { 1386 if (index >= 1) { 1387 return NULL; 1388 } 1389 1390 return new OggSource(this); 1391 } 1392 1393 sp<MetaData> OggExtractor::getTrackMetaData( 1394 size_t index, uint32_t /* flags */) { 1395 if (index >= 1) { 1396 return NULL; 1397 } 1398 1399 return mImpl->getFormat(); 1400 } 1401 1402 sp<MetaData> OggExtractor::getMetaData() { 1403 return mImpl->getFileMetaData(); 1404 } 1405 1406 bool SniffOgg( 1407 const sp<DataSource> &source, String8 *mimeType, float *confidence, 1408 sp<AMessage> *) { 1409 char tmp[4]; 1410 if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 1411 return false; 1412 } 1413 1414 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 1415 *confidence = 0.2f; 1416 1417 return true; 1418 } 1419 1420 } // namespace android 1421