• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &currentPageSamples)) {
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