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