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