OggExtractor.cpp revision 20e7a377ce22e260772f0c0276870cee5a92648e
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 36extern "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 45namespace android { 46 47struct 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 58protected: 59 virtual ~OggSource(); 60 61private: 62 sp<OggExtractor> mExtractor; 63 bool mStarted; 64 65 OggSource(const OggSource &); 66 OggSource &operator=(const OggSource &); 67}; 68 69struct 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 90protected: 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 165struct 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 179protected: 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 187struct 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 204protected: 205 virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; 206 virtual status_t verifyHeader(MediaBuffer *buffer, uint8_t type); 207 208private: 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 218static void extractAlbumArt( 219 const sp<MetaData> &fileMeta, const void *data, size_t size); 220 221//////////////////////////////////////////////////////////////////////////////// 222 223OggSource::OggSource(const sp<OggExtractor> &extractor) 224 : mExtractor(extractor), 225 mStarted(false) { 226} 227 228OggSource::~OggSource() { 229 if (mStarted) { 230 stop(); 231 } 232} 233 234sp<MetaData> OggSource::getFormat() { 235 return mExtractor->mImpl->getFormat(); 236} 237 238status_t OggSource::start(MetaData * /* params */) { 239 if (mStarted) { 240 return INVALID_OPERATION; 241 } 242 243 mStarted = true; 244 245 return OK; 246} 247 248status_t OggSource::stop() { 249 mStarted = false; 250 251 return OK; 252} 253 254status_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 292MyOggExtractor::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 315MyOggExtractor::~MyOggExtractor() { 316 vorbis_comment_clear(&mVc); 317 vorbis_info_clear(&mVi); 318} 319 320sp<MetaData> MyOggExtractor::getFormat() const { 321 return mMeta; 322} 323 324status_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. 355status_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 409status_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 457status_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 490ssize_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 561status_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 618uint32_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 664status_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 // Prevent a harmless unsigned integer overflow by clamping to 0 774 if (mCurrentPage.mGranulePosition >= mPrevGranulePosition) { 775 mCurrentPageSamples = 776 mCurrentPage.mGranulePosition - mPrevGranulePosition; 777 } else { 778 mCurrentPageSamples = 0; 779 } 780 mFirstPacketInPage = true; 781 782 mPrevGranulePosition = mCurrentPage.mGranulePosition; 783 784 mCurrentPageSize = n; 785 mNextLaceIndex = 0; 786 787 if (buffer != NULL) { 788 if ((mCurrentPage.mFlags & 1) == 0) { 789 // This page does not continue the packet, i.e. the packet 790 // is already complete. 791 792 if (timeUs >= 0) { 793 buffer->meta_data()->setInt64(kKeyTime, timeUs); 794 } 795 796 buffer->meta_data()->setInt32( 797 kKeyValidSamples, mCurrentPageSamples); 798 mFirstPacketInPage = false; 799 800 *out = buffer; 801 802 return OK; 803 } 804 } 805 } 806} 807 808status_t MyOggExtractor::init() { 809 mMeta = new MetaData; 810 mMeta->setCString(kKeyMIMEType, mMimeType); 811 812 status_t err; 813 MediaBuffer *packet; 814 for (size_t i = 0; i < mNumHeaders; ++i) { 815 // ignore timestamp for configuration packets 816 if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) { 817 return err; 818 } 819 ALOGV("read packet of size %zu\n", packet->range_length()); 820 err = verifyHeader(packet, /* type = */ i * 2 + 1); 821 packet->release(); 822 packet = NULL; 823 if (err != OK) { 824 return err; 825 } 826 } 827 828 mFirstDataOffset = mOffset + mCurrentPageSize; 829 830 off64_t size; 831 uint64_t lastGranulePosition; 832 if (!(mSource->flags() & DataSource::kIsCachingDataSource) 833 && mSource->getSize(&size) == OK 834 && findPrevGranulePosition(size, &lastGranulePosition) == OK) { 835 // Let's assume it's cheap to seek to the end. 836 // The granule position of the final page in the stream will 837 // give us the exact duration of the content, something that 838 // we can only approximate using avg. bitrate if seeking to 839 // the end is too expensive or impossible (live streaming). 840 841 int64_t durationUs = getTimeUsOfGranule(lastGranulePosition); 842 843 mMeta->setInt64(kKeyDuration, durationUs); 844 845 buildTableOfContents(); 846 } 847 848 return OK; 849} 850 851void MyOggExtractor::buildTableOfContents() { 852 off64_t offset = mFirstDataOffset; 853 Page page; 854 ssize_t pageSize; 855 while ((pageSize = readPage(offset, &page)) > 0) { 856 mTableOfContents.push(); 857 858 TOCEntry &entry = 859 mTableOfContents.editItemAt(mTableOfContents.size() - 1); 860 861 entry.mPageOffset = offset; 862 entry.mTimeUs = getTimeUsOfGranule(page.mGranulePosition); 863 864 offset += (size_t)pageSize; 865 } 866 867 // Limit the maximum amount of RAM we spend on the table of contents, 868 // if necessary thin out the table evenly to trim it down to maximum 869 // size. 870 871 static const size_t kMaxTOCSize = 8192; 872 static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry); 873 874 size_t numerator = mTableOfContents.size(); 875 876 if (numerator > kMaxNumTOCEntries) { 877 size_t denom = numerator - kMaxNumTOCEntries; 878 879 size_t accum = 0; 880 for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) { 881 accum += denom; 882 if (accum >= numerator) { 883 mTableOfContents.removeAt(i); 884 accum -= numerator; 885 } 886 } 887 } 888} 889 890int32_t MyOggExtractor::getPacketBlockSize(MediaBuffer *buffer) { 891 const uint8_t *data = 892 (const uint8_t *)buffer->data() + buffer->range_offset(); 893 894 size_t size = buffer->range_length(); 895 896 ogg_buffer buf; 897 buf.data = (uint8_t *)data; 898 buf.size = size; 899 buf.refcount = 1; 900 buf.ptr.owner = NULL; 901 902 ogg_reference ref; 903 ref.buffer = &buf; 904 ref.begin = 0; 905 ref.length = size; 906 ref.next = NULL; 907 908 ogg_packet pack; 909 pack.packet = &ref; 910 pack.bytes = ref.length; 911 pack.b_o_s = 0; 912 pack.e_o_s = 0; 913 pack.granulepos = 0; 914 pack.packetno = 0; 915 916 return vorbis_packet_blocksize(&mVi, &pack); 917} 918 919int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const { 920 uint64_t pcmSamplePosition = 0; 921 if (granulePos > mCodecDelay) { 922 pcmSamplePosition = granulePos - mCodecDelay; 923 } 924 return pcmSamplePosition * 1000000ll / kOpusSampleRate; 925} 926 927status_t MyOpusExtractor::verifyHeader(MediaBuffer *buffer, uint8_t type) { 928 switch (type) { 929 // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean 930 // header and comments such that we can share code with MyVorbisExtractor. 931 case 1: 932 return verifyOpusHeader(buffer); 933 case 3: 934 return verifyOpusComments(buffer); 935 default: 936 return INVALID_OPERATION; 937 } 938} 939 940status_t MyOpusExtractor::verifyOpusHeader(MediaBuffer *buffer) { 941 const size_t kOpusHeaderSize = 19; 942 const uint8_t *data = 943 (const uint8_t *)buffer->data() + buffer->range_offset(); 944 945 size_t size = buffer->range_length(); 946 947 if (size < kOpusHeaderSize 948 || memcmp(data, "OpusHead", 8) 949 || /* version = */ data[8] != 1) { 950 return ERROR_MALFORMED; 951 } 952 953 mChannelCount = data[9]; 954 mCodecDelay = U16LE_AT(&data[10]); 955 956 mMeta->setData(kKeyOpusHeader, 0, data, size); 957 mMeta->setInt32(kKeySampleRate, kOpusSampleRate); 958 mMeta->setInt32(kKeyChannelCount, mChannelCount); 959 mMeta->setInt64(kKeyOpusSeekPreRoll /* ns */, kOpusSeekPreRollUs * 1000 /* = 80 ms*/); 960 mMeta->setInt64(kKeyOpusCodecDelay /* ns */, 961 mCodecDelay /* sample/s */ * 1000000000 / kOpusSampleRate); 962 963 return OK; 964} 965 966status_t MyOpusExtractor::verifyOpusComments(MediaBuffer *buffer) { 967 // add artificial framing bit so we can reuse _vorbis_unpack_comment 968 int32_t commentSize = buffer->range_length() + 1; 969 sp<ABuffer> aBuf = new ABuffer(commentSize); 970 if (aBuf->capacity() <= buffer->range_length()) { 971 return ERROR_MALFORMED; 972 } 973 974 uint8_t* commentData = aBuf->data(); 975 memcpy(commentData, 976 (uint8_t *)buffer->data() + buffer->range_offset(), 977 buffer->range_length()); 978 979 ogg_buffer buf; 980 buf.data = commentData; 981 buf.size = commentSize; 982 buf.refcount = 1; 983 buf.ptr.owner = NULL; 984 985 ogg_reference ref; 986 ref.buffer = &buf; 987 ref.begin = 0; 988 ref.length = commentSize; 989 ref.next = NULL; 990 991 oggpack_buffer bits; 992 oggpack_readinit(&bits, &ref); 993 994 // skip 'OpusTags' 995 const char *OpusTags = "OpusTags"; 996 const int32_t headerLen = strlen(OpusTags); 997 int32_t framingBitOffset = headerLen; 998 for (int i = 0; i < headerLen; ++i) { 999 char chr = oggpack_read(&bits, 8); 1000 if (chr != OpusTags[i]) { 1001 return ERROR_MALFORMED; 1002 } 1003 } 1004 1005 int32_t vendorLen = oggpack_read(&bits, 32); 1006 framingBitOffset += 4; 1007 if (vendorLen < 0 || vendorLen > commentSize - 8) { 1008 return ERROR_MALFORMED; 1009 } 1010 // skip vendor string 1011 framingBitOffset += vendorLen; 1012 for (int i = 0; i < vendorLen; ++i) { 1013 oggpack_read(&bits, 8); 1014 } 1015 1016 int32_t n = oggpack_read(&bits, 32); 1017 framingBitOffset += 4; 1018 if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { 1019 return ERROR_MALFORMED; 1020 } 1021 for (int i = 0; i < n; ++i) { 1022 int32_t len = oggpack_read(&bits, 32); 1023 framingBitOffset += 4; 1024 if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { 1025 return ERROR_MALFORMED; 1026 } 1027 framingBitOffset += len; 1028 for (int j = 0; j < len; ++j) { 1029 oggpack_read(&bits, 8); 1030 } 1031 } 1032 if (framingBitOffset < 0 || framingBitOffset >= commentSize) { 1033 return ERROR_MALFORMED; 1034 } 1035 commentData[framingBitOffset] = 1; 1036 1037 buf.data = commentData + headerLen; 1038 buf.size = commentSize - headerLen; 1039 buf.refcount = 1; 1040 buf.ptr.owner = NULL; 1041 1042 ref.buffer = &buf; 1043 ref.begin = 0; 1044 ref.length = commentSize - headerLen; 1045 ref.next = NULL; 1046 1047 oggpack_readinit(&bits, &ref); 1048 int err = _vorbis_unpack_comment(&mVc, &bits); 1049 if (0 != err) { 1050 return ERROR_MALFORMED; 1051 } 1052 1053 parseFileMetaData(); 1054 return OK; 1055} 1056 1057status_t MyVorbisExtractor::verifyHeader( 1058 MediaBuffer *buffer, uint8_t type) { 1059 const uint8_t *data = 1060 (const uint8_t *)buffer->data() + buffer->range_offset(); 1061 1062 size_t size = buffer->range_length(); 1063 1064 if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { 1065 return ERROR_MALFORMED; 1066 } 1067 1068 ogg_buffer buf; 1069 buf.data = (uint8_t *)data; 1070 buf.size = size; 1071 buf.refcount = 1; 1072 buf.ptr.owner = NULL; 1073 1074 ogg_reference ref; 1075 ref.buffer = &buf; 1076 ref.begin = 0; 1077 ref.length = size; 1078 ref.next = NULL; 1079 1080 oggpack_buffer bits; 1081 oggpack_readinit(&bits, &ref); 1082 1083 if (oggpack_read(&bits, 8) != type) { 1084 return ERROR_MALFORMED; 1085 } 1086 for (size_t i = 0; i < 6; ++i) { 1087 oggpack_read(&bits, 8); // skip 'vorbis' 1088 } 1089 1090 switch (type) { 1091 case 1: 1092 { 1093 if (0 != _vorbis_unpack_info(&mVi, &bits)) { 1094 return ERROR_MALFORMED; 1095 } 1096 1097 mMeta->setData(kKeyVorbisInfo, 0, data, size); 1098 mMeta->setInt32(kKeySampleRate, mVi.rate); 1099 mMeta->setInt32(kKeyChannelCount, mVi.channels); 1100 1101 ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); 1102 ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); 1103 ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 1104 ALOGV("window-bitrate = %ld", mVi.bitrate_window); 1105 ALOGV("blocksizes: %d/%d", 1106 vorbis_info_blocksize(&mVi, 0), 1107 vorbis_info_blocksize(&mVi, 1) 1108 ); 1109 1110 off64_t size; 1111 if (mSource->getSize(&size) == OK) { 1112 uint64_t bps = approxBitrate(); 1113 if (bps != 0) { 1114 mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 1115 } 1116 } 1117 break; 1118 } 1119 1120 case 3: 1121 { 1122 if (0 != _vorbis_unpack_comment(&mVc, &bits)) { 1123 return ERROR_MALFORMED; 1124 } 1125 1126 parseFileMetaData(); 1127 break; 1128 } 1129 1130 case 5: 1131 { 1132 if (0 != _vorbis_unpack_books(&mVi, &bits)) { 1133 return ERROR_MALFORMED; 1134 } 1135 1136 mMeta->setData(kKeyVorbisBooks, 0, data, size); 1137 break; 1138 } 1139 } 1140 1141 return OK; 1142} 1143 1144uint64_t MyVorbisExtractor::approxBitrate() const { 1145 if (mVi.bitrate_nominal != 0) { 1146 return mVi.bitrate_nominal; 1147 } 1148 1149 return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 1150} 1151 1152void MyOggExtractor::parseFileMetaData() { 1153 mFileMeta = new MetaData; 1154 mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 1155 1156 for (int i = 0; i < mVc.comments; ++i) { 1157 const char *comment = mVc.user_comments[i]; 1158 size_t commentLength = mVc.comment_lengths[i]; 1159 parseVorbisComment(mFileMeta, comment, commentLength); 1160 //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); 1161 } 1162} 1163 1164void parseVorbisComment( 1165 const sp<MetaData> &fileMeta, const char *comment, size_t commentLength) 1166{ 1167 struct { 1168 const char *const mTag; 1169 uint32_t mKey; 1170 } kMap[] = { 1171 { "TITLE", kKeyTitle }, 1172 { "ARTIST", kKeyArtist }, 1173 { "ALBUMARTIST", kKeyAlbumArtist }, 1174 { "ALBUM ARTIST", kKeyAlbumArtist }, 1175 { "COMPILATION", kKeyCompilation }, 1176 { "ALBUM", kKeyAlbum }, 1177 { "COMPOSER", kKeyComposer }, 1178 { "GENRE", kKeyGenre }, 1179 { "AUTHOR", kKeyAuthor }, 1180 { "TRACKNUMBER", kKeyCDTrackNumber }, 1181 { "DISCNUMBER", kKeyDiscNumber }, 1182 { "DATE", kKeyDate }, 1183 { "YEAR", kKeyYear }, 1184 { "LYRICIST", kKeyWriter }, 1185 { "METADATA_BLOCK_PICTURE", kKeyAlbumArt }, 1186 { "ANDROID_LOOP", kKeyAutoLoop }, 1187 }; 1188 1189 for (size_t j = 0; j < sizeof(kMap) / sizeof(kMap[0]); ++j) { 1190 size_t tagLen = strlen(kMap[j].mTag); 1191 if (!strncasecmp(kMap[j].mTag, comment, tagLen) 1192 && comment[tagLen] == '=') { 1193 if (kMap[j].mKey == kKeyAlbumArt) { 1194 extractAlbumArt( 1195 fileMeta, 1196 &comment[tagLen + 1], 1197 commentLength - tagLen - 1); 1198 } else if (kMap[j].mKey == kKeyAutoLoop) { 1199 if (!strcasecmp(&comment[tagLen + 1], "true")) { 1200 fileMeta->setInt32(kKeyAutoLoop, true); 1201 } 1202 } else { 1203 fileMeta->setCString(kMap[j].mKey, &comment[tagLen + 1]); 1204 } 1205 } 1206 } 1207 1208} 1209 1210// The returned buffer should be free()d. 1211static uint8_t *DecodeBase64(const char *s, size_t size, size_t *outSize) { 1212 *outSize = 0; 1213 1214 if ((size % 4) != 0) { 1215 return NULL; 1216 } 1217 1218 size_t n = size; 1219 size_t padding = 0; 1220 if (n >= 1 && s[n - 1] == '=') { 1221 padding = 1; 1222 1223 if (n >= 2 && s[n - 2] == '=') { 1224 padding = 2; 1225 } 1226 } 1227 1228 size_t outLen = 3 * size / 4 - padding; 1229 1230 *outSize = outLen; 1231 1232 void *buffer = malloc(outLen); 1233 1234 uint8_t *out = (uint8_t *)buffer; 1235 size_t j = 0; 1236 uint32_t accum = 0; 1237 for (size_t i = 0; i < n; ++i) { 1238 char c = s[i]; 1239 unsigned value; 1240 if (c >= 'A' && c <= 'Z') { 1241 value = c - 'A'; 1242 } else if (c >= 'a' && c <= 'z') { 1243 value = 26 + c - 'a'; 1244 } else if (c >= '0' && c <= '9') { 1245 value = 52 + c - '0'; 1246 } else if (c == '+') { 1247 value = 62; 1248 } else if (c == '/') { 1249 value = 63; 1250 } else if (c != '=') { 1251 return NULL; 1252 } else { 1253 if (i < n - padding) { 1254 return NULL; 1255 } 1256 1257 value = 0; 1258 } 1259 1260 accum = (accum << 6) | value; 1261 1262 if (((i + 1) % 4) == 0) { 1263 out[j++] = (accum >> 16); 1264 1265 if (j < outLen) { out[j++] = (accum >> 8) & 0xff; } 1266 if (j < outLen) { out[j++] = accum & 0xff; } 1267 1268 accum = 0; 1269 } 1270 } 1271 1272 return (uint8_t *)buffer; 1273} 1274 1275static void extractAlbumArt( 1276 const sp<MetaData> &fileMeta, const void *data, size_t size) { 1277 ALOGV("extractAlbumArt from '%s'", (const char *)data); 1278 1279 size_t flacSize; 1280 uint8_t *flac = DecodeBase64((const char *)data, size, &flacSize); 1281 1282 if (flac == NULL) { 1283 ALOGE("malformed base64 encoded data."); 1284 return; 1285 } 1286 1287 ALOGV("got flac of size %zu", flacSize); 1288 1289 uint32_t picType; 1290 uint32_t typeLen; 1291 uint32_t descLen; 1292 uint32_t dataLen; 1293 char type[128]; 1294 1295 if (flacSize < 8) { 1296 goto exit; 1297 } 1298 1299 picType = U32_AT(flac); 1300 1301 if (picType != 3) { 1302 // This is not a front cover. 1303 goto exit; 1304 } 1305 1306 typeLen = U32_AT(&flac[4]); 1307 if (typeLen > sizeof(type) - 1) { 1308 goto exit; 1309 } 1310 1311 // we've already checked above that flacSize >= 8 1312 if (flacSize - 8 < typeLen) { 1313 goto exit; 1314 } 1315 1316 memcpy(type, &flac[8], typeLen); 1317 type[typeLen] = '\0'; 1318 1319 ALOGV("picType = %d, type = '%s'", picType, type); 1320 1321 if (!strcmp(type, "-->")) { 1322 // This is not inline cover art, but an external url instead. 1323 goto exit; 1324 } 1325 1326 descLen = U32_AT(&flac[8 + typeLen]); 1327 1328 if (flacSize < 32 || 1329 flacSize - 32 < typeLen || 1330 flacSize - 32 - typeLen < descLen) { 1331 goto exit; 1332 } 1333 1334 dataLen = U32_AT(&flac[8 + typeLen + 4 + descLen + 16]); 1335 1336 1337 // we've already checked above that (flacSize - 32 - typeLen - descLen) >= 0 1338 if (flacSize - 32 - typeLen - descLen < dataLen) { 1339 goto exit; 1340 } 1341 1342 ALOGV("got image data, %zu trailing bytes", 1343 flacSize - 32 - typeLen - descLen - dataLen); 1344 1345 fileMeta->setData( 1346 kKeyAlbumArt, 0, &flac[8 + typeLen + 4 + descLen + 20], dataLen); 1347 1348 fileMeta->setCString(kKeyAlbumArtMIME, type); 1349 1350exit: 1351 free(flac); 1352 flac = NULL; 1353} 1354 1355//////////////////////////////////////////////////////////////////////////////// 1356 1357OggExtractor::OggExtractor(const sp<DataSource> &source) 1358 : mDataSource(source), 1359 mInitCheck(NO_INIT), 1360 mImpl(NULL) { 1361 for (int i = 0; i < 2; ++i) { 1362 if (mImpl != NULL) { 1363 delete mImpl; 1364 } 1365 if (i == 0) { 1366 mImpl = new MyVorbisExtractor(mDataSource); 1367 } else { 1368 mImpl = new MyOpusExtractor(mDataSource); 1369 } 1370 mInitCheck = mImpl->seekToOffset(0); 1371 1372 if (mInitCheck == OK) { 1373 mInitCheck = mImpl->init(); 1374 if (mInitCheck == OK) { 1375 break; 1376 } 1377 } 1378 } 1379} 1380 1381OggExtractor::~OggExtractor() { 1382 delete mImpl; 1383 mImpl = NULL; 1384} 1385 1386size_t OggExtractor::countTracks() { 1387 return mInitCheck != OK ? 0 : 1; 1388} 1389 1390sp<MediaSource> OggExtractor::getTrack(size_t index) { 1391 if (index >= 1) { 1392 return NULL; 1393 } 1394 1395 return new OggSource(this); 1396} 1397 1398sp<MetaData> OggExtractor::getTrackMetaData( 1399 size_t index, uint32_t /* flags */) { 1400 if (index >= 1) { 1401 return NULL; 1402 } 1403 1404 return mImpl->getFormat(); 1405} 1406 1407sp<MetaData> OggExtractor::getMetaData() { 1408 return mImpl->getFileMetaData(); 1409} 1410 1411bool SniffOgg( 1412 const sp<DataSource> &source, String8 *mimeType, float *confidence, 1413 sp<AMessage> *) { 1414 char tmp[4]; 1415 if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 1416 return false; 1417 } 1418 1419 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 1420 *confidence = 0.2f; 1421 1422 return true; 1423} 1424 1425} // namespace android 1426