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/DataSource.h> 25 #include <media/stagefright/MediaBuffer.h> 26 #include <media/stagefright/MediaBufferGroup.h> 27 #include <media/stagefright/MediaDebug.h> 28 #include <media/stagefright/MediaDefs.h> 29 #include <media/stagefright/MediaErrors.h> 30 #include <media/stagefright/MediaSource.h> 31 #include <media/stagefright/MetaData.h> 32 #include <media/stagefright/Utils.h> 33 #include <utils/String8.h> 34 35 extern "C" { 36 #include <Tremolo/codec_internal.h> 37 38 int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb); 39 int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb); 40 int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb); 41 } 42 43 namespace android { 44 45 struct OggSource : public MediaSource { 46 OggSource(const sp<OggExtractor> &extractor); 47 48 virtual sp<MetaData> getFormat(); 49 50 virtual status_t start(MetaData *params = NULL); 51 virtual status_t stop(); 52 53 virtual status_t read( 54 MediaBuffer **buffer, const ReadOptions *options = NULL); 55 56 protected: 57 virtual ~OggSource(); 58 59 private: 60 sp<OggExtractor> mExtractor; 61 bool mStarted; 62 63 OggSource(const OggSource &); 64 OggSource &operator=(const OggSource &); 65 }; 66 67 struct MyVorbisExtractor { 68 MyVorbisExtractor(const sp<DataSource> &source); 69 virtual ~MyVorbisExtractor(); 70 71 sp<MetaData> getFormat() const; 72 73 // Returns an approximate bitrate in bits per second. 74 uint64_t approxBitrate(); 75 76 status_t seekToOffset(off_t offset); 77 status_t readNextPacket(MediaBuffer **buffer); 78 79 void init(); 80 81 private: 82 struct Page { 83 uint64_t mGranulePosition; 84 uint32_t mSerialNo; 85 uint32_t mPageNo; 86 uint8_t mFlags; 87 uint8_t mNumSegments; 88 uint8_t mLace[255]; 89 }; 90 91 sp<DataSource> mSource; 92 off_t mOffset; 93 Page mCurrentPage; 94 size_t mCurrentPageSize; 95 size_t mNextLaceIndex; 96 97 off_t mFirstDataOffset; 98 99 vorbis_info mVi; 100 vorbis_comment mVc; 101 102 sp<MetaData> mMeta; 103 104 ssize_t readPage(off_t offset, Page *page); 105 status_t findNextPage(off_t startOffset, off_t *pageOffset); 106 107 void verifyHeader( 108 MediaBuffer *buffer, uint8_t type); 109 110 MyVorbisExtractor(const MyVorbisExtractor &); 111 MyVorbisExtractor &operator=(const MyVorbisExtractor &); 112 }; 113 114 //////////////////////////////////////////////////////////////////////////////// 115 116 OggSource::OggSource(const sp<OggExtractor> &extractor) 117 : mExtractor(extractor), 118 mStarted(false) { 119 } 120 121 OggSource::~OggSource() { 122 if (mStarted) { 123 stop(); 124 } 125 } 126 127 sp<MetaData> OggSource::getFormat() { 128 return mExtractor->mImpl->getFormat(); 129 } 130 131 status_t OggSource::start(MetaData *params) { 132 if (mStarted) { 133 return INVALID_OPERATION; 134 } 135 136 mStarted = true; 137 138 return OK; 139 } 140 141 status_t OggSource::stop() { 142 mStarted = false; 143 144 return OK; 145 } 146 147 status_t OggSource::read( 148 MediaBuffer **out, const ReadOptions *options) { 149 *out = NULL; 150 151 int64_t seekTimeUs; 152 if (options && options->getSeekTo(&seekTimeUs)) { 153 off_t pos = seekTimeUs * mExtractor->mImpl->approxBitrate() / 8000000ll; 154 LOGI("seeking to offset %ld", pos); 155 156 if (mExtractor->mImpl->seekToOffset(pos) != OK) { 157 return ERROR_END_OF_STREAM; 158 } 159 } 160 161 MediaBuffer *packet; 162 status_t err = mExtractor->mImpl->readNextPacket(&packet); 163 164 if (err != OK) { 165 return err; 166 } 167 168 #if 0 169 int64_t timeUs; 170 if (packet->meta_data()->findInt64(kKeyTime, &timeUs)) { 171 LOGI("found time = %lld us", timeUs); 172 } else { 173 LOGI("NO time"); 174 } 175 #endif 176 177 *out = packet; 178 179 return OK; 180 } 181 182 //////////////////////////////////////////////////////////////////////////////// 183 184 MyVorbisExtractor::MyVorbisExtractor(const sp<DataSource> &source) 185 : mSource(source), 186 mOffset(0), 187 mCurrentPageSize(0), 188 mNextLaceIndex(0), 189 mFirstDataOffset(-1) { 190 mCurrentPage.mNumSegments = 0; 191 } 192 193 MyVorbisExtractor::~MyVorbisExtractor() { 194 } 195 196 sp<MetaData> MyVorbisExtractor::getFormat() const { 197 return mMeta; 198 } 199 200 status_t MyVorbisExtractor::findNextPage( 201 off_t startOffset, off_t *pageOffset) { 202 *pageOffset = startOffset; 203 204 for (;;) { 205 char signature[4]; 206 ssize_t n = mSource->readAt(*pageOffset, &signature, 4); 207 208 if (n < 4) { 209 *pageOffset = 0; 210 211 return (n < 0) ? n : (status_t)ERROR_END_OF_STREAM; 212 } 213 214 if (!memcmp(signature, "OggS", 4)) { 215 if (*pageOffset > startOffset) { 216 LOGV("skipped %ld bytes of junk to reach next frame", 217 *pageOffset - startOffset); 218 } 219 220 return OK; 221 } 222 223 ++*pageOffset; 224 } 225 } 226 227 status_t MyVorbisExtractor::seekToOffset(off_t offset) { 228 if (mFirstDataOffset >= 0 && offset < mFirstDataOffset) { 229 // Once we know where the actual audio data starts (past the headers) 230 // don't ever seek to anywhere before that. 231 offset = mFirstDataOffset; 232 } 233 234 off_t pageOffset; 235 status_t err = findNextPage(offset, &pageOffset); 236 237 if (err != OK) { 238 return err; 239 } 240 241 mOffset = pageOffset; 242 243 mCurrentPageSize = 0; 244 mCurrentPage.mNumSegments = 0; 245 mNextLaceIndex = 0; 246 247 // XXX what if new page continues packet from last??? 248 249 return OK; 250 } 251 252 ssize_t MyVorbisExtractor::readPage(off_t offset, Page *page) { 253 uint8_t header[27]; 254 if (mSource->readAt(offset, header, sizeof(header)) 255 < (ssize_t)sizeof(header)) { 256 LOGE("failed to read %d bytes at offset 0x%08lx", sizeof(header), offset); 257 258 return ERROR_IO; 259 } 260 261 if (memcmp(header, "OggS", 4)) { 262 return ERROR_MALFORMED; 263 } 264 265 if (header[4] != 0) { 266 // Wrong version. 267 268 return ERROR_UNSUPPORTED; 269 } 270 271 page->mFlags = header[5]; 272 273 if (page->mFlags & ~7) { 274 // Only bits 0-2 are defined in version 0. 275 return ERROR_MALFORMED; 276 } 277 278 page->mGranulePosition = U64LE_AT(&header[6]); 279 280 #if 0 281 printf("granulePosition = %llu (0x%llx)\n", 282 page->mGranulePosition, page->mGranulePosition); 283 #endif 284 285 page->mSerialNo = U32LE_AT(&header[14]); 286 page->mPageNo = U32LE_AT(&header[18]); 287 288 page->mNumSegments = header[26]; 289 if (mSource->readAt( 290 offset + sizeof(header), page->mLace, page->mNumSegments) 291 < (ssize_t)page->mNumSegments) { 292 return ERROR_IO; 293 } 294 295 size_t totalSize = 0;; 296 for (size_t i = 0; i < page->mNumSegments; ++i) { 297 totalSize += page->mLace[i]; 298 } 299 300 String8 tmp; 301 for (size_t i = 0; i < page->mNumSegments; ++i) { 302 char x[32]; 303 sprintf(x, "%s%u", i > 0 ? ", " : "", (unsigned)page->mLace[i]); 304 305 tmp.append(x); 306 } 307 308 LOGV("%c %s", page->mFlags & 1 ? '+' : ' ', tmp.string()); 309 310 return sizeof(header) + page->mNumSegments + totalSize; 311 } 312 313 status_t MyVorbisExtractor::readNextPacket(MediaBuffer **out) { 314 *out = NULL; 315 316 MediaBuffer *buffer = NULL; 317 int64_t timeUs = -1; 318 319 for (;;) { 320 size_t i; 321 size_t packetSize = 0; 322 bool gotFullPacket = false; 323 for (i = mNextLaceIndex; i < mCurrentPage.mNumSegments; ++i) { 324 uint8_t lace = mCurrentPage.mLace[i]; 325 326 packetSize += lace; 327 328 if (lace < 255) { 329 gotFullPacket = true; 330 ++i; 331 break; 332 } 333 } 334 335 if (mNextLaceIndex < mCurrentPage.mNumSegments) { 336 off_t dataOffset = mOffset + 27 + mCurrentPage.mNumSegments; 337 for (size_t j = 0; j < mNextLaceIndex; ++j) { 338 dataOffset += mCurrentPage.mLace[j]; 339 } 340 341 size_t fullSize = packetSize; 342 if (buffer != NULL) { 343 fullSize += buffer->range_length(); 344 } 345 MediaBuffer *tmp = new MediaBuffer(fullSize); 346 if (buffer != NULL) { 347 memcpy(tmp->data(), buffer->data(), buffer->range_length()); 348 tmp->set_range(0, buffer->range_length()); 349 buffer->release(); 350 } else { 351 // XXX Not only is this not technically the correct time for 352 // this packet, we also stamp every packet in this page 353 // with the same time. This needs fixing later. 354 timeUs = mCurrentPage.mGranulePosition * 1000000ll / mVi.rate; 355 tmp->set_range(0, 0); 356 } 357 buffer = tmp; 358 359 ssize_t n = mSource->readAt( 360 dataOffset, 361 (uint8_t *)buffer->data() + buffer->range_length(), 362 packetSize); 363 364 if (n < (ssize_t)packetSize) { 365 LOGE("failed to read %d bytes at 0x%08lx", packetSize, dataOffset); 366 return ERROR_IO; 367 } 368 369 buffer->set_range(0, fullSize); 370 371 mNextLaceIndex = i; 372 373 if (gotFullPacket) { 374 // We've just read the entire packet. 375 376 if (timeUs >= 0) { 377 buffer->meta_data()->setInt64(kKeyTime, timeUs); 378 } 379 380 *out = buffer; 381 382 return OK; 383 } 384 385 // fall through, the buffer now contains the start of the packet. 386 } 387 388 CHECK_EQ(mNextLaceIndex, mCurrentPage.mNumSegments); 389 390 mOffset += mCurrentPageSize; 391 ssize_t n = readPage(mOffset, &mCurrentPage); 392 393 if (n <= 0) { 394 if (buffer) { 395 buffer->release(); 396 buffer = NULL; 397 } 398 399 LOGE("readPage returned %ld", n); 400 401 return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; 402 } 403 404 mCurrentPageSize = n; 405 mNextLaceIndex = 0; 406 407 if (buffer != NULL) { 408 if ((mCurrentPage.mFlags & 1) == 0) { 409 // This page does not continue the packet, i.e. the packet 410 // is already complete. 411 412 if (timeUs >= 0) { 413 buffer->meta_data()->setInt64(kKeyTime, timeUs); 414 } 415 416 *out = buffer; 417 418 return OK; 419 } 420 } 421 } 422 } 423 424 void MyVorbisExtractor::init() { 425 vorbis_info_init(&mVi); 426 427 vorbis_comment mVc; 428 429 mMeta = new MetaData; 430 mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_VORBIS); 431 432 MediaBuffer *packet; 433 CHECK_EQ(readNextPacket(&packet), OK); 434 LOGV("read packet of size %d\n", packet->range_length()); 435 verifyHeader(packet, 1); 436 packet->release(); 437 packet = NULL; 438 439 CHECK_EQ(readNextPacket(&packet), OK); 440 LOGV("read packet of size %d\n", packet->range_length()); 441 verifyHeader(packet, 3); 442 packet->release(); 443 packet = NULL; 444 445 CHECK_EQ(readNextPacket(&packet), OK); 446 LOGV("read packet of size %d\n", packet->range_length()); 447 verifyHeader(packet, 5); 448 packet->release(); 449 packet = NULL; 450 451 mFirstDataOffset = mOffset + mCurrentPageSize; 452 } 453 454 void MyVorbisExtractor::verifyHeader( 455 MediaBuffer *buffer, uint8_t type) { 456 const uint8_t *data = 457 (const uint8_t *)buffer->data() + buffer->range_offset(); 458 459 size_t size = buffer->range_length(); 460 461 CHECK(size >= 7); 462 463 CHECK_EQ(data[0], type); 464 CHECK(!memcmp(&data[1], "vorbis", 6)); 465 466 ogg_buffer buf; 467 buf.data = (uint8_t *)data; 468 buf.size = size; 469 buf.refcount = 1; 470 buf.ptr.owner = NULL; 471 472 ogg_reference ref; 473 ref.buffer = &buf; 474 ref.begin = 0; 475 ref.length = size; 476 ref.next = NULL; 477 478 oggpack_buffer bits; 479 oggpack_readinit(&bits, &ref); 480 481 CHECK_EQ(oggpack_read(&bits, 8), type); 482 for (size_t i = 0; i < 6; ++i) { 483 oggpack_read(&bits, 8); // skip 'vorbis' 484 } 485 486 switch (type) { 487 case 1: 488 { 489 CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); 490 491 mMeta->setData(kKeyVorbisInfo, 0, data, size); 492 mMeta->setInt32(kKeySampleRate, mVi.rate); 493 mMeta->setInt32(kKeyChannelCount, mVi.channels); 494 495 LOGV("lower-bitrate = %ld", mVi.bitrate_lower); 496 LOGV("upper-bitrate = %ld", mVi.bitrate_upper); 497 LOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); 498 LOGV("window-bitrate = %ld", mVi.bitrate_window); 499 500 off_t size; 501 if (mSource->getSize(&size) == OK) { 502 uint64_t bps = approxBitrate(); 503 504 mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); 505 } 506 break; 507 } 508 509 case 3: 510 { 511 CHECK_EQ(0, _vorbis_unpack_comment(&mVc, &bits)); 512 break; 513 } 514 515 case 5: 516 { 517 CHECK_EQ(0, _vorbis_unpack_books(&mVi, &bits)); 518 519 mMeta->setData(kKeyVorbisBooks, 0, data, size); 520 break; 521 } 522 } 523 } 524 525 uint64_t MyVorbisExtractor::approxBitrate() { 526 if (mVi.bitrate_nominal != 0) { 527 return mVi.bitrate_nominal; 528 } 529 530 return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; 531 } 532 533 //////////////////////////////////////////////////////////////////////////////// 534 535 OggExtractor::OggExtractor(const sp<DataSource> &source) 536 : mDataSource(source), 537 mInitCheck(NO_INIT), 538 mImpl(NULL) { 539 mImpl = new MyVorbisExtractor(mDataSource); 540 CHECK_EQ(mImpl->seekToOffset(0), OK); 541 mImpl->init(); 542 543 mInitCheck = OK; 544 } 545 546 OggExtractor::~OggExtractor() { 547 delete mImpl; 548 mImpl = NULL; 549 } 550 551 size_t OggExtractor::countTracks() { 552 return mInitCheck != OK ? 0 : 1; 553 } 554 555 sp<MediaSource> OggExtractor::getTrack(size_t index) { 556 if (index >= 1) { 557 return NULL; 558 } 559 560 return new OggSource(this); 561 } 562 563 sp<MetaData> OggExtractor::getTrackMetaData( 564 size_t index, uint32_t flags) { 565 if (index >= 1) { 566 return NULL; 567 } 568 569 return mImpl->getFormat(); 570 } 571 572 sp<MetaData> OggExtractor::getMetaData() { 573 sp<MetaData> meta = new MetaData; 574 575 if (mInitCheck != OK) { 576 return meta; 577 } 578 579 meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); 580 581 return meta; 582 } 583 584 bool SniffOgg( 585 const sp<DataSource> &source, String8 *mimeType, float *confidence) { 586 char tmp[4]; 587 if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) { 588 return false; 589 } 590 591 mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_OGG); 592 *confidence = 0.2f; 593 594 return true; 595 } 596 597 } // namespace android 598