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