Loading media/extractors/ogg/OggExtractor.cpp +57 −57 Original line number Original line Diff line number Diff line Loading @@ -84,7 +84,7 @@ struct MyOggExtractor { status_t seekToTime(int64_t timeUs); status_t seekToTime(int64_t timeUs); status_t seekToOffset(off64_t offset); status_t seekToOffset(off64_t offset); virtual status_t readNextPacket(MediaBufferBase **buffer) = 0; virtual media_status_t readNextPacket(MediaBufferBase **buffer) = 0; status_t init(); status_t init(); Loading Loading @@ -145,7 +145,7 @@ protected: // 1 - bitstream identification header // 1 - bitstream identification header // 3 - comment header // 3 - comment header // 5 - codec setup header (Vorbis only) // 5 - codec setup header (Vorbis only) virtual status_t verifyHeader(MediaBufferBase *buffer, uint8_t type) = 0; virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type) = 0; // Read the next ogg packet from the underlying data source; optionally // Read the next ogg packet from the underlying data source; optionally // calculate the timestamp for the output packet whilst pretending // calculate the timestamp for the output packet whilst pretending Loading @@ -153,7 +153,7 @@ protected: // // // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated; // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated; // clients are responsible for releasing the original buffer. // clients are responsible for releasing the original buffer. status_t _readNextPacket(MediaBufferBase **buffer, bool calcVorbisTimestamp); media_status_t _readNextPacket(MediaBufferBase **buffer, bool calcVorbisTimestamp); int32_t getPacketBlockSize(MediaBufferBase *buffer); int32_t getPacketBlockSize(MediaBufferBase *buffer); Loading @@ -177,7 +177,7 @@ struct MyVorbisExtractor : public MyOggExtractor { virtual uint64_t approxBitrate() const; virtual uint64_t approxBitrate() const; virtual status_t readNextPacket(MediaBufferBase **buffer) { virtual media_status_t readNextPacket(MediaBufferBase **buffer) { return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true); return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true); } } Loading @@ -189,7 +189,7 @@ protected: return granulePos * 1000000ll / mVi.rate; return granulePos * 1000000ll / mVi.rate; } } virtual status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); }; }; struct MyOpusExtractor : public MyOggExtractor { struct MyOpusExtractor : public MyOggExtractor { Loading @@ -207,15 +207,15 @@ struct MyOpusExtractor : public MyOggExtractor { return 0; return 0; } } virtual status_t readNextPacket(MediaBufferBase **buffer); virtual media_status_t readNextPacket(MediaBufferBase **buffer); protected: protected: virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; virtual status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); private: private: status_t verifyOpusHeader(MediaBufferBase *buffer); media_status_t verifyOpusHeader(MediaBufferBase *buffer); status_t verifyOpusComments(MediaBufferBase *buffer); media_status_t verifyOpusComments(MediaBufferBase *buffer); uint32_t getNumSamplesInPacket(MediaBufferBase *buffer) const; uint32_t getNumSamplesInPacket(MediaBufferBase *buffer) const; uint8_t mChannelCount; uint8_t mChannelCount; Loading Loading @@ -270,10 +270,10 @@ media_status_t OggSource::read( } } MediaBufferBase *packet; MediaBufferBase *packet; status_t err = mExtractor->mImpl->readNextPacket(&packet); media_status_t err = mExtractor->mImpl->readNextPacket(&packet); if (err != OK) { if (err != AMEDIA_OK) { return AMEDIA_ERROR_UNKNOWN; return err; } } #if 0 #if 0 Loading Loading @@ -507,27 +507,27 @@ ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { if (n < 0) { if (n < 0) { return n; return n; } else if (n == 0) { } else if (n == 0) { return ERROR_END_OF_STREAM; return AMEDIA_ERROR_END_OF_STREAM; } else { } else { return ERROR_IO; return AMEDIA_ERROR_IO; } } } } if (memcmp(header, "OggS", 4)) { if (memcmp(header, "OggS", 4)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } if (header[4] != 0) { if (header[4] != 0) { // Wrong version. // Wrong version. return ERROR_UNSUPPORTED; return AMEDIA_ERROR_UNSUPPORTED; } } page->mFlags = header[5]; page->mFlags = header[5]; if (page->mFlags & ~7) { if (page->mFlags & ~7) { // Only bits 0-2 are defined in version 0. // Only bits 0-2 are defined in version 0. return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } page->mGranulePosition = U64LE_AT(&header[6]); page->mGranulePosition = U64LE_AT(&header[6]); Loading @@ -544,7 +544,7 @@ ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { if (mSource->readAt( if (mSource->readAt( offset + sizeof(header), page->mLace, page->mNumSegments) offset + sizeof(header), page->mLace, page->mNumSegments) < (ssize_t)page->mNumSegments) { < (ssize_t)page->mNumSegments) { return ERROR_IO; return AMEDIA_ERROR_IO; } } size_t totalSize = 0;; size_t totalSize = 0;; Loading @@ -567,7 +567,7 @@ ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { return sizeof(header) + page->mNumSegments + totalSize; return sizeof(header) + page->mNumSegments + totalSize; } } status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { media_status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) { if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) { // The first sample might not start at time 0; find out where by subtracting // The first sample might not start at time 0; find out where by subtracting // the number of samples on the first page from the granule position // the number of samples on the first page from the granule position Loading @@ -577,12 +577,12 @@ status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { uint32_t numSamples = 0; uint32_t numSamples = 0; uint64_t curGranulePosition = 0; uint64_t curGranulePosition = 0; while (true) { while (true) { status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false); media_status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false); if (err != OK && err != ERROR_END_OF_STREAM) { if (err != AMEDIA_OK && err != AMEDIA_ERROR_END_OF_STREAM) { return err; return err; } } // First two pages are header pages. // First two pages are header pages. if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) { if (err == AMEDIA_ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) { if (mBuf != NULL) { if (mBuf != NULL) { mBuf->release(); mBuf->release(); mBuf = NULL; mBuf = NULL; Loading @@ -603,8 +603,8 @@ status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { seekToOffset(0); seekToOffset(0); } } status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false); media_status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false); if (err != OK) { if (err != AMEDIA_OK) { return err; return err; } } Loading @@ -625,7 +625,7 @@ status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { uint32_t frames = getNumSamplesInPacket(*out); uint32_t frames = getNumSamplesInPacket(*out); mCurGranulePosition += frames; mCurGranulePosition += frames; return OK; return AMEDIA_OK; } } uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const { uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const { Loading Loading @@ -674,7 +674,7 @@ uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const { return numSamples; return numSamples; } } status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisTimestamp) { media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisTimestamp) { *out = NULL; *out = NULL; MediaBufferBase *buffer = NULL; MediaBufferBase *buffer = NULL; Loading Loading @@ -711,7 +711,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT buffer->release(); buffer->release(); } } ALOGE("b/36592202"); ALOGE("b/36592202"); return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } MediaBufferBase *tmp = MediaBufferBase::Create(fullSize); MediaBufferBase *tmp = MediaBufferBase::Create(fullSize); if (tmp == NULL) { if (tmp == NULL) { Loading @@ -719,7 +719,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT buffer->release(); buffer->release(); } } ALOGE("b/36592202"); ALOGE("b/36592202"); return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } if (buffer != NULL) { if (buffer != NULL) { memcpy(tmp->data(), buffer->data(), buffer->range_length()); memcpy(tmp->data(), buffer->data(), buffer->range_length()); Loading @@ -739,7 +739,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT buffer->release(); buffer->release(); ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes", ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes", packetSize, (long long)dataOffset, n); packetSize, (long long)dataOffset, n); return ERROR_IO; return AMEDIA_ERROR_IO; } } buffer->set_range(0, fullSize); buffer->set_range(0, fullSize); Loading Loading @@ -776,7 +776,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT } } *out = buffer; *out = buffer; return OK; return AMEDIA_OK; } } // fall through, the buffer now contains the start of the packet. // fall through, the buffer now contains the start of the packet. Loading @@ -795,7 +795,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT ALOGV("readPage returned %zd", n); ALOGV("readPage returned %zd", n); return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; return n < 0 ? (media_status_t) n : AMEDIA_ERROR_END_OF_STREAM; } } // Prevent a harmless unsigned integer overflow by clamping to 0 // Prevent a harmless unsigned integer overflow by clamping to 0 Loading Loading @@ -827,7 +827,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT *out = buffer; *out = buffer; return OK; return AMEDIA_OK; } } } } } } Loading @@ -836,18 +836,18 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT status_t MyOggExtractor::init() { status_t MyOggExtractor::init() { AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType); AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType); status_t err; media_status_t err; MediaBufferBase *packet; MediaBufferBase *packet; for (size_t i = 0; i < mNumHeaders; ++i) { for (size_t i = 0; i < mNumHeaders; ++i) { // ignore timestamp for configuration packets // ignore timestamp for configuration packets if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) { if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) { return err; return err; } } ALOGV("read packet of size %zu\n", packet->range_length()); ALOGV("read packet of size %zu\n", packet->range_length()); err = verifyHeader(packet, /* type = */ i * 2 + 1); err = verifyHeader(packet, /* type = */ i * 2 + 1); packet->release(); packet->release(); packet = NULL; packet = NULL; if (err != OK) { if (err != AMEDIA_OK) { return err; return err; } } } } Loading @@ -872,7 +872,7 @@ status_t MyOggExtractor::init() { buildTableOfContents(); buildTableOfContents(); } } return OK; return AMEDIA_OK; } } void MyOggExtractor::buildTableOfContents() { void MyOggExtractor::buildTableOfContents() { Loading Loading @@ -954,7 +954,7 @@ int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const { return pcmSamplePosition * 1000000ll / kOpusSampleRate; return pcmSamplePosition * 1000000ll / kOpusSampleRate; } } status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) { media_status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) { switch (type) { switch (type) { // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean // header and comments such that we can share code with MyVorbisExtractor. // header and comments such that we can share code with MyVorbisExtractor. Loading @@ -963,11 +963,11 @@ status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) { case 3: case 3: return verifyOpusComments(buffer); return verifyOpusComments(buffer); default: default: return INVALID_OPERATION; return AMEDIA_ERROR_INVALID_OPERATION; } } } } status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { media_status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { const size_t kOpusHeaderSize = 19; const size_t kOpusHeaderSize = 19; const uint8_t *data = const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); (const uint8_t *)buffer->data() + buffer->range_offset(); Loading @@ -977,7 +977,7 @@ status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { if (size < kOpusHeaderSize if (size < kOpusHeaderSize || memcmp(data, "OpusHead", 8) || memcmp(data, "OpusHead", 8) || /* version = */ data[8] != 1) { || /* version = */ data[8] != 1) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } mChannelCount = data[9]; mChannelCount = data[9]; Loading @@ -993,16 +993,16 @@ status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_1, AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_1, mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate); mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate); return OK; return AMEDIA_OK; } } status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { // add artificial framing bit so we can reuse _vorbis_unpack_comment // add artificial framing bit so we can reuse _vorbis_unpack_comment int32_t commentSize = buffer->range_length() + 1; int32_t commentSize = buffer->range_length() + 1; auto tmp = heapbuffer<uint8_t>(commentSize); auto tmp = heapbuffer<uint8_t>(commentSize); uint8_t *commentData = tmp.get(); uint8_t *commentData = tmp.get(); if (commentData == nullptr) { if (commentData == nullptr) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } memcpy(commentData, memcpy(commentData, Loading Loading @@ -1031,14 +1031,14 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { for (int i = 0; i < headerLen; ++i) { for (int i = 0; i < headerLen; ++i) { char chr = oggpack_read(&bits, 8); char chr = oggpack_read(&bits, 8); if (chr != OpusTags[i]) { if (chr != OpusTags[i]) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } } } int32_t vendorLen = oggpack_read(&bits, 32); int32_t vendorLen = oggpack_read(&bits, 32); framingBitOffset += 4; framingBitOffset += 4; if (vendorLen < 0 || vendorLen > commentSize - 8) { if (vendorLen < 0 || vendorLen > commentSize - 8) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } // skip vendor string // skip vendor string framingBitOffset += vendorLen; framingBitOffset += vendorLen; Loading @@ -1049,13 +1049,13 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { int32_t n = oggpack_read(&bits, 32); int32_t n = oggpack_read(&bits, 32); framingBitOffset += 4; framingBitOffset += 4; if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) { int32_t len = oggpack_read(&bits, 32); int32_t len = oggpack_read(&bits, 32); framingBitOffset += 4; framingBitOffset += 4; if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } framingBitOffset += len; framingBitOffset += len; for (int j = 0; j < len; ++j) { for (int j = 0; j < len; ++j) { Loading @@ -1063,7 +1063,7 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { } } } } if (framingBitOffset < 0 || framingBitOffset >= commentSize) { if (framingBitOffset < 0 || framingBitOffset >= commentSize) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } commentData[framingBitOffset] = 1; commentData[framingBitOffset] = 1; Loading @@ -1080,14 +1080,14 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { oggpack_readinit(&bits, &ref); oggpack_readinit(&bits, &ref); int err = _vorbis_unpack_comment(&mVc, &bits); int err = _vorbis_unpack_comment(&mVc, &bits); if (0 != err) { if (0 != err) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } parseFileMetaData(); parseFileMetaData(); return OK; return AMEDIA_OK; } } status_t MyVorbisExtractor::verifyHeader( media_status_t MyVorbisExtractor::verifyHeader( MediaBufferBase *buffer, uint8_t type) { MediaBufferBase *buffer, uint8_t type) { const uint8_t *data = const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); (const uint8_t *)buffer->data() + buffer->range_offset(); Loading @@ -1095,7 +1095,7 @@ status_t MyVorbisExtractor::verifyHeader( size_t size = buffer->range_length(); size_t size = buffer->range_length(); if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } ogg_buffer buf; ogg_buffer buf; Loading @@ -1114,7 +1114,7 @@ status_t MyVorbisExtractor::verifyHeader( oggpack_readinit(&bits, &ref); oggpack_readinit(&bits, &ref); if (oggpack_read(&bits, 8) != type) { if (oggpack_read(&bits, 8) != type) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } for (size_t i = 0; i < 6; ++i) { for (size_t i = 0; i < 6; ++i) { oggpack_read(&bits, 8); // skip 'vorbis' oggpack_read(&bits, 8); // skip 'vorbis' Loading @@ -1124,7 +1124,7 @@ status_t MyVorbisExtractor::verifyHeader( case 1: case 1: { { if (0 != _vorbis_unpack_info(&mVi, &bits)) { if (0 != _vorbis_unpack_info(&mVi, &bits)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size); AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size); Loading Loading @@ -1154,7 +1154,7 @@ status_t MyVorbisExtractor::verifyHeader( case 3: case 3: { { if (0 != _vorbis_unpack_comment(&mVc, &bits)) { if (0 != _vorbis_unpack_comment(&mVc, &bits)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } parseFileMetaData(); parseFileMetaData(); Loading @@ -1164,7 +1164,7 @@ status_t MyVorbisExtractor::verifyHeader( case 5: case 5: { { if (0 != _vorbis_unpack_books(&mVi, &bits)) { if (0 != _vorbis_unpack_books(&mVi, &bits)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, data, size); AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, data, size); Loading @@ -1172,7 +1172,7 @@ status_t MyVorbisExtractor::verifyHeader( } } } } return OK; return AMEDIA_OK; } } uint64_t MyVorbisExtractor::approxBitrate() const { uint64_t MyVorbisExtractor::approxBitrate() const { Loading media/libmedia/NdkMediaErrorPriv.cpp +12 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,12 @@ media_status_t translate_error(status_t err) { return AMEDIA_ERROR_END_OF_STREAM; return AMEDIA_ERROR_END_OF_STREAM; } else if (err == ERROR_IO) { } else if (err == ERROR_IO) { return AMEDIA_ERROR_IO; return AMEDIA_ERROR_IO; } else if (err == ERROR_MALFORMED) { return AMEDIA_ERROR_MALFORMED; } else if (err == INVALID_OPERATION) { return AMEDIA_ERROR_INVALID_OPERATION; } else if (err == UNKNOWN_ERROR) { return AMEDIA_ERROR_UNKNOWN; } } ALOGE("sf error code: %d", err); ALOGE("sf error code: %d", err); Loading @@ -45,6 +51,12 @@ status_t reverse_translate_error(media_status_t err) { return ERROR_IO; return ERROR_IO; } else if (err == AMEDIA_ERROR_WOULD_BLOCK) { } else if (err == AMEDIA_ERROR_WOULD_BLOCK) { return WOULD_BLOCK; return WOULD_BLOCK; } else if (err == AMEDIA_ERROR_MALFORMED) { return ERROR_MALFORMED; } else if (err == AMEDIA_ERROR_INVALID_OPERATION) { return INVALID_OPERATION; } else if (err == AMEDIA_ERROR_UNKNOWN) { return UNKNOWN_ERROR; } } ALOGE("ndk error code: %d", err); ALOGE("ndk error code: %d", err); Loading Loading
media/extractors/ogg/OggExtractor.cpp +57 −57 Original line number Original line Diff line number Diff line Loading @@ -84,7 +84,7 @@ struct MyOggExtractor { status_t seekToTime(int64_t timeUs); status_t seekToTime(int64_t timeUs); status_t seekToOffset(off64_t offset); status_t seekToOffset(off64_t offset); virtual status_t readNextPacket(MediaBufferBase **buffer) = 0; virtual media_status_t readNextPacket(MediaBufferBase **buffer) = 0; status_t init(); status_t init(); Loading Loading @@ -145,7 +145,7 @@ protected: // 1 - bitstream identification header // 1 - bitstream identification header // 3 - comment header // 3 - comment header // 5 - codec setup header (Vorbis only) // 5 - codec setup header (Vorbis only) virtual status_t verifyHeader(MediaBufferBase *buffer, uint8_t type) = 0; virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type) = 0; // Read the next ogg packet from the underlying data source; optionally // Read the next ogg packet from the underlying data source; optionally // calculate the timestamp for the output packet whilst pretending // calculate the timestamp for the output packet whilst pretending Loading @@ -153,7 +153,7 @@ protected: // // // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated; // *buffer is NULL'ed out immediately upon entry, and if successful a new buffer is allocated; // clients are responsible for releasing the original buffer. // clients are responsible for releasing the original buffer. status_t _readNextPacket(MediaBufferBase **buffer, bool calcVorbisTimestamp); media_status_t _readNextPacket(MediaBufferBase **buffer, bool calcVorbisTimestamp); int32_t getPacketBlockSize(MediaBufferBase *buffer); int32_t getPacketBlockSize(MediaBufferBase *buffer); Loading @@ -177,7 +177,7 @@ struct MyVorbisExtractor : public MyOggExtractor { virtual uint64_t approxBitrate() const; virtual uint64_t approxBitrate() const; virtual status_t readNextPacket(MediaBufferBase **buffer) { virtual media_status_t readNextPacket(MediaBufferBase **buffer) { return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true); return _readNextPacket(buffer, /* calcVorbisTimestamp = */ true); } } Loading @@ -189,7 +189,7 @@ protected: return granulePos * 1000000ll / mVi.rate; return granulePos * 1000000ll / mVi.rate; } } virtual status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); }; }; struct MyOpusExtractor : public MyOggExtractor { struct MyOpusExtractor : public MyOggExtractor { Loading @@ -207,15 +207,15 @@ struct MyOpusExtractor : public MyOggExtractor { return 0; return 0; } } virtual status_t readNextPacket(MediaBufferBase **buffer); virtual media_status_t readNextPacket(MediaBufferBase **buffer); protected: protected: virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; virtual int64_t getTimeUsOfGranule(uint64_t granulePos) const; virtual status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); virtual media_status_t verifyHeader(MediaBufferBase *buffer, uint8_t type); private: private: status_t verifyOpusHeader(MediaBufferBase *buffer); media_status_t verifyOpusHeader(MediaBufferBase *buffer); status_t verifyOpusComments(MediaBufferBase *buffer); media_status_t verifyOpusComments(MediaBufferBase *buffer); uint32_t getNumSamplesInPacket(MediaBufferBase *buffer) const; uint32_t getNumSamplesInPacket(MediaBufferBase *buffer) const; uint8_t mChannelCount; uint8_t mChannelCount; Loading Loading @@ -270,10 +270,10 @@ media_status_t OggSource::read( } } MediaBufferBase *packet; MediaBufferBase *packet; status_t err = mExtractor->mImpl->readNextPacket(&packet); media_status_t err = mExtractor->mImpl->readNextPacket(&packet); if (err != OK) { if (err != AMEDIA_OK) { return AMEDIA_ERROR_UNKNOWN; return err; } } #if 0 #if 0 Loading Loading @@ -507,27 +507,27 @@ ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { if (n < 0) { if (n < 0) { return n; return n; } else if (n == 0) { } else if (n == 0) { return ERROR_END_OF_STREAM; return AMEDIA_ERROR_END_OF_STREAM; } else { } else { return ERROR_IO; return AMEDIA_ERROR_IO; } } } } if (memcmp(header, "OggS", 4)) { if (memcmp(header, "OggS", 4)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } if (header[4] != 0) { if (header[4] != 0) { // Wrong version. // Wrong version. return ERROR_UNSUPPORTED; return AMEDIA_ERROR_UNSUPPORTED; } } page->mFlags = header[5]; page->mFlags = header[5]; if (page->mFlags & ~7) { if (page->mFlags & ~7) { // Only bits 0-2 are defined in version 0. // Only bits 0-2 are defined in version 0. return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } page->mGranulePosition = U64LE_AT(&header[6]); page->mGranulePosition = U64LE_AT(&header[6]); Loading @@ -544,7 +544,7 @@ ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { if (mSource->readAt( if (mSource->readAt( offset + sizeof(header), page->mLace, page->mNumSegments) offset + sizeof(header), page->mLace, page->mNumSegments) < (ssize_t)page->mNumSegments) { < (ssize_t)page->mNumSegments) { return ERROR_IO; return AMEDIA_ERROR_IO; } } size_t totalSize = 0;; size_t totalSize = 0;; Loading @@ -567,7 +567,7 @@ ssize_t MyOggExtractor::readPage(off64_t offset, Page *page) { return sizeof(header) + page->mNumSegments + totalSize; return sizeof(header) + page->mNumSegments + totalSize; } } status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { media_status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) { if (mOffset <= mFirstDataOffset && mStartGranulePosition < 0) { // The first sample might not start at time 0; find out where by subtracting // The first sample might not start at time 0; find out where by subtracting // the number of samples on the first page from the granule position // the number of samples on the first page from the granule position Loading @@ -577,12 +577,12 @@ status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { uint32_t numSamples = 0; uint32_t numSamples = 0; uint64_t curGranulePosition = 0; uint64_t curGranulePosition = 0; while (true) { while (true) { status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false); media_status_t err = _readNextPacket(&mBuf, /* calcVorbisTimestamp = */false); if (err != OK && err != ERROR_END_OF_STREAM) { if (err != AMEDIA_OK && err != AMEDIA_ERROR_END_OF_STREAM) { return err; return err; } } // First two pages are header pages. // First two pages are header pages. if (err == ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) { if (err == AMEDIA_ERROR_END_OF_STREAM || mCurrentPage.mPageNo > 2) { if (mBuf != NULL) { if (mBuf != NULL) { mBuf->release(); mBuf->release(); mBuf = NULL; mBuf = NULL; Loading @@ -603,8 +603,8 @@ status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { seekToOffset(0); seekToOffset(0); } } status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false); media_status_t err = _readNextPacket(out, /* calcVorbisTimestamp = */false); if (err != OK) { if (err != AMEDIA_OK) { return err; return err; } } Loading @@ -625,7 +625,7 @@ status_t MyOpusExtractor::readNextPacket(MediaBufferBase **out) { uint32_t frames = getNumSamplesInPacket(*out); uint32_t frames = getNumSamplesInPacket(*out); mCurGranulePosition += frames; mCurGranulePosition += frames; return OK; return AMEDIA_OK; } } uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const { uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const { Loading Loading @@ -674,7 +674,7 @@ uint32_t MyOpusExtractor::getNumSamplesInPacket(MediaBufferBase *buffer) const { return numSamples; return numSamples; } } status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisTimestamp) { media_status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisTimestamp) { *out = NULL; *out = NULL; MediaBufferBase *buffer = NULL; MediaBufferBase *buffer = NULL; Loading Loading @@ -711,7 +711,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT buffer->release(); buffer->release(); } } ALOGE("b/36592202"); ALOGE("b/36592202"); return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } MediaBufferBase *tmp = MediaBufferBase::Create(fullSize); MediaBufferBase *tmp = MediaBufferBase::Create(fullSize); if (tmp == NULL) { if (tmp == NULL) { Loading @@ -719,7 +719,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT buffer->release(); buffer->release(); } } ALOGE("b/36592202"); ALOGE("b/36592202"); return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } if (buffer != NULL) { if (buffer != NULL) { memcpy(tmp->data(), buffer->data(), buffer->range_length()); memcpy(tmp->data(), buffer->data(), buffer->range_length()); Loading @@ -739,7 +739,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT buffer->release(); buffer->release(); ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes", ALOGV("failed to read %zu bytes at %#016llx, got %zd bytes", packetSize, (long long)dataOffset, n); packetSize, (long long)dataOffset, n); return ERROR_IO; return AMEDIA_ERROR_IO; } } buffer->set_range(0, fullSize); buffer->set_range(0, fullSize); Loading Loading @@ -776,7 +776,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT } } *out = buffer; *out = buffer; return OK; return AMEDIA_OK; } } // fall through, the buffer now contains the start of the packet. // fall through, the buffer now contains the start of the packet. Loading @@ -795,7 +795,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT ALOGV("readPage returned %zd", n); ALOGV("readPage returned %zd", n); return n < 0 ? n : (status_t)ERROR_END_OF_STREAM; return n < 0 ? (media_status_t) n : AMEDIA_ERROR_END_OF_STREAM; } } // Prevent a harmless unsigned integer overflow by clamping to 0 // Prevent a harmless unsigned integer overflow by clamping to 0 Loading Loading @@ -827,7 +827,7 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT *out = buffer; *out = buffer; return OK; return AMEDIA_OK; } } } } } } Loading @@ -836,18 +836,18 @@ status_t MyOggExtractor::_readNextPacket(MediaBufferBase **out, bool calcVorbisT status_t MyOggExtractor::init() { status_t MyOggExtractor::init() { AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType); AMediaFormat_setString(mMeta, AMEDIAFORMAT_KEY_MIME, mMimeType); status_t err; media_status_t err; MediaBufferBase *packet; MediaBufferBase *packet; for (size_t i = 0; i < mNumHeaders; ++i) { for (size_t i = 0; i < mNumHeaders; ++i) { // ignore timestamp for configuration packets // ignore timestamp for configuration packets if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != OK) { if ((err = _readNextPacket(&packet, /* calcVorbisTimestamp = */ false)) != AMEDIA_OK) { return err; return err; } } ALOGV("read packet of size %zu\n", packet->range_length()); ALOGV("read packet of size %zu\n", packet->range_length()); err = verifyHeader(packet, /* type = */ i * 2 + 1); err = verifyHeader(packet, /* type = */ i * 2 + 1); packet->release(); packet->release(); packet = NULL; packet = NULL; if (err != OK) { if (err != AMEDIA_OK) { return err; return err; } } } } Loading @@ -872,7 +872,7 @@ status_t MyOggExtractor::init() { buildTableOfContents(); buildTableOfContents(); } } return OK; return AMEDIA_OK; } } void MyOggExtractor::buildTableOfContents() { void MyOggExtractor::buildTableOfContents() { Loading Loading @@ -954,7 +954,7 @@ int64_t MyOpusExtractor::getTimeUsOfGranule(uint64_t granulePos) const { return pcmSamplePosition * 1000000ll / kOpusSampleRate; return pcmSamplePosition * 1000000ll / kOpusSampleRate; } } status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) { media_status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) { switch (type) { switch (type) { // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean // there are actually no header types defined in the Opus spec; we choose 1 and 3 to mean // header and comments such that we can share code with MyVorbisExtractor. // header and comments such that we can share code with MyVorbisExtractor. Loading @@ -963,11 +963,11 @@ status_t MyOpusExtractor::verifyHeader(MediaBufferBase *buffer, uint8_t type) { case 3: case 3: return verifyOpusComments(buffer); return verifyOpusComments(buffer); default: default: return INVALID_OPERATION; return AMEDIA_ERROR_INVALID_OPERATION; } } } } status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { media_status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { const size_t kOpusHeaderSize = 19; const size_t kOpusHeaderSize = 19; const uint8_t *data = const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); (const uint8_t *)buffer->data() + buffer->range_offset(); Loading @@ -977,7 +977,7 @@ status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { if (size < kOpusHeaderSize if (size < kOpusHeaderSize || memcmp(data, "OpusHead", 8) || memcmp(data, "OpusHead", 8) || /* version = */ data[8] != 1) { || /* version = */ data[8] != 1) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } mChannelCount = data[9]; mChannelCount = data[9]; Loading @@ -993,16 +993,16 @@ status_t MyOpusExtractor::verifyOpusHeader(MediaBufferBase *buffer) { AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_1, AMediaFormat_setInt64(mMeta, AMEDIAFORMAT_KEY_CSD_1, mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate); mCodecDelay /* sample/s */ * 1000000000ll / kOpusSampleRate); return OK; return AMEDIA_OK; } } status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { media_status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { // add artificial framing bit so we can reuse _vorbis_unpack_comment // add artificial framing bit so we can reuse _vorbis_unpack_comment int32_t commentSize = buffer->range_length() + 1; int32_t commentSize = buffer->range_length() + 1; auto tmp = heapbuffer<uint8_t>(commentSize); auto tmp = heapbuffer<uint8_t>(commentSize); uint8_t *commentData = tmp.get(); uint8_t *commentData = tmp.get(); if (commentData == nullptr) { if (commentData == nullptr) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } memcpy(commentData, memcpy(commentData, Loading Loading @@ -1031,14 +1031,14 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { for (int i = 0; i < headerLen; ++i) { for (int i = 0; i < headerLen; ++i) { char chr = oggpack_read(&bits, 8); char chr = oggpack_read(&bits, 8); if (chr != OpusTags[i]) { if (chr != OpusTags[i]) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } } } int32_t vendorLen = oggpack_read(&bits, 32); int32_t vendorLen = oggpack_read(&bits, 32); framingBitOffset += 4; framingBitOffset += 4; if (vendorLen < 0 || vendorLen > commentSize - 8) { if (vendorLen < 0 || vendorLen > commentSize - 8) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } // skip vendor string // skip vendor string framingBitOffset += vendorLen; framingBitOffset += vendorLen; Loading @@ -1049,13 +1049,13 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { int32_t n = oggpack_read(&bits, 32); int32_t n = oggpack_read(&bits, 32); framingBitOffset += 4; framingBitOffset += 4; if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { if (n < 0 || n > ((commentSize - oggpack_bytes(&bits)) >> 2)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i) { int32_t len = oggpack_read(&bits, 32); int32_t len = oggpack_read(&bits, 32); framingBitOffset += 4; framingBitOffset += 4; if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { if (len < 0 || len > (commentSize - oggpack_bytes(&bits))) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } framingBitOffset += len; framingBitOffset += len; for (int j = 0; j < len; ++j) { for (int j = 0; j < len; ++j) { Loading @@ -1063,7 +1063,7 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { } } } } if (framingBitOffset < 0 || framingBitOffset >= commentSize) { if (framingBitOffset < 0 || framingBitOffset >= commentSize) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } commentData[framingBitOffset] = 1; commentData[framingBitOffset] = 1; Loading @@ -1080,14 +1080,14 @@ status_t MyOpusExtractor::verifyOpusComments(MediaBufferBase *buffer) { oggpack_readinit(&bits, &ref); oggpack_readinit(&bits, &ref); int err = _vorbis_unpack_comment(&mVc, &bits); int err = _vorbis_unpack_comment(&mVc, &bits); if (0 != err) { if (0 != err) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } parseFileMetaData(); parseFileMetaData(); return OK; return AMEDIA_OK; } } status_t MyVorbisExtractor::verifyHeader( media_status_t MyVorbisExtractor::verifyHeader( MediaBufferBase *buffer, uint8_t type) { MediaBufferBase *buffer, uint8_t type) { const uint8_t *data = const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); (const uint8_t *)buffer->data() + buffer->range_offset(); Loading @@ -1095,7 +1095,7 @@ status_t MyVorbisExtractor::verifyHeader( size_t size = buffer->range_length(); size_t size = buffer->range_length(); if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } ogg_buffer buf; ogg_buffer buf; Loading @@ -1114,7 +1114,7 @@ status_t MyVorbisExtractor::verifyHeader( oggpack_readinit(&bits, &ref); oggpack_readinit(&bits, &ref); if (oggpack_read(&bits, 8) != type) { if (oggpack_read(&bits, 8) != type) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } for (size_t i = 0; i < 6; ++i) { for (size_t i = 0; i < 6; ++i) { oggpack_read(&bits, 8); // skip 'vorbis' oggpack_read(&bits, 8); // skip 'vorbis' Loading @@ -1124,7 +1124,7 @@ status_t MyVorbisExtractor::verifyHeader( case 1: case 1: { { if (0 != _vorbis_unpack_info(&mVi, &bits)) { if (0 != _vorbis_unpack_info(&mVi, &bits)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size); AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_0, data, size); Loading Loading @@ -1154,7 +1154,7 @@ status_t MyVorbisExtractor::verifyHeader( case 3: case 3: { { if (0 != _vorbis_unpack_comment(&mVc, &bits)) { if (0 != _vorbis_unpack_comment(&mVc, &bits)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } parseFileMetaData(); parseFileMetaData(); Loading @@ -1164,7 +1164,7 @@ status_t MyVorbisExtractor::verifyHeader( case 5: case 5: { { if (0 != _vorbis_unpack_books(&mVi, &bits)) { if (0 != _vorbis_unpack_books(&mVi, &bits)) { return ERROR_MALFORMED; return AMEDIA_ERROR_MALFORMED; } } AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, data, size); AMediaFormat_setBuffer(mMeta, AMEDIAFORMAT_KEY_CSD_1, data, size); Loading @@ -1172,7 +1172,7 @@ status_t MyVorbisExtractor::verifyHeader( } } } } return OK; return AMEDIA_OK; } } uint64_t MyVorbisExtractor::approxBitrate() const { uint64_t MyVorbisExtractor::approxBitrate() const { Loading
media/libmedia/NdkMediaErrorPriv.cpp +12 −0 Original line number Original line Diff line number Diff line Loading @@ -29,6 +29,12 @@ media_status_t translate_error(status_t err) { return AMEDIA_ERROR_END_OF_STREAM; return AMEDIA_ERROR_END_OF_STREAM; } else if (err == ERROR_IO) { } else if (err == ERROR_IO) { return AMEDIA_ERROR_IO; return AMEDIA_ERROR_IO; } else if (err == ERROR_MALFORMED) { return AMEDIA_ERROR_MALFORMED; } else if (err == INVALID_OPERATION) { return AMEDIA_ERROR_INVALID_OPERATION; } else if (err == UNKNOWN_ERROR) { return AMEDIA_ERROR_UNKNOWN; } } ALOGE("sf error code: %d", err); ALOGE("sf error code: %d", err); Loading @@ -45,6 +51,12 @@ status_t reverse_translate_error(media_status_t err) { return ERROR_IO; return ERROR_IO; } else if (err == AMEDIA_ERROR_WOULD_BLOCK) { } else if (err == AMEDIA_ERROR_WOULD_BLOCK) { return WOULD_BLOCK; return WOULD_BLOCK; } else if (err == AMEDIA_ERROR_MALFORMED) { return ERROR_MALFORMED; } else if (err == AMEDIA_ERROR_INVALID_OPERATION) { return INVALID_OPERATION; } else if (err == AMEDIA_ERROR_UNKNOWN) { return UNKNOWN_ERROR; } } ALOGE("ndk error code: %d", err); ALOGE("ndk error code: %d", err); Loading