AMRExtractor::AMRExtractor(const sp<DataSource> &source) : mDataSource(source), mInitCheck(NO_INIT), mOffsetTableLength(0) { String8 mimeType; float confidence; if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) { return; } mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB); mMeta = new MetaData; mMeta->setCString( kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AMR_NB); mMeta->setInt32(kKeyChannelCount, 1); mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000); off64_t offset = mIsWide ? 9 : 6; off64_t streamSize; size_t frameSize, numFrames = 0; int64_t duration = 0; if (mDataSource->getSize(&streamSize) == OK) { while (offset < streamSize) { status_t status = getFrameSizeByOffset(source, offset, mIsWide, &frameSize); if (status == ERROR_END_OF_STREAM) { break; } else if (status != OK) { return; } if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) { CHECK_EQ(mOffsetTableLength, numFrames / 50); mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6); mOffsetTableLength ++; } offset += frameSize; duration += 20000; // Each frame is 20ms numFrames ++; } mMeta->setInt64(kKeyDuration, duration); } mInitCheck = OK; }
status_t AMRSource::read( MediaBuffer **out, const ReadOptions *options) { *out = NULL; int64_t seekTimeUs; ReadOptions::SeekMode mode; if (mOffsetTableLength > 0 && options && options->getSeekTo(&seekTimeUs, &mode)) { size_t size; int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. mCurrentTimeUs = seekFrame * 20000ll; size_t index = seekFrame < 0 ? 0 : seekFrame / 50; if (index >= mOffsetTableLength) { index = mOffsetTableLength - 1; } mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6); for (size_t i = 0; i< seekFrame - index * 50; i++) { status_t err; if ((err = getFrameSizeByOffset(mDataSource, mOffset, mIsWide, &size)) != OK) { return err; } mOffset += size; } } uint8_t header; ssize_t n = mDataSource->readAt(mOffset, &header, 1); if (n < 1) { return ERROR_END_OF_STREAM; } if (header & 0x83) { // Padding bits must be 0. ALOGE("padding bits must be 0, header is 0x%02x", header); return ERROR_MALFORMED; } unsigned FT = (header >> 3) & 0x0f; size_t frameSize = getFrameSize(mIsWide, FT); if (frameSize == 0) { return ERROR_MALFORMED; } MediaBuffer *buffer; status_t err = mGroup->acquire_buffer(&buffer); if (err != OK) { return err; } n = mDataSource->readAt(mOffset, buffer->data(), frameSize); if (n != (ssize_t)frameSize) { buffer->release(); buffer = NULL; if (n < 0) { return ERROR_IO; } else { // only partial frame is available, treat it as EOS. mOffset += n; return ERROR_END_OF_STREAM; } } buffer->set_range(0, frameSize); buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); mOffset += frameSize; mCurrentTimeUs += 20000; // Each frame is 20ms *out = buffer; return OK; }
status_t AMRSource::read( MediaBuffer **out, const ReadOptions *options) { *out = NULL; int64_t seekTimeUs; ReadOptions::SeekMode mode; if (options && options->getSeekTo(&seekTimeUs, &mode)) { #ifdef MTK_AOSP_ENHANCEMENT // Maybe risk (int)index >= (uint)mOffsetTableLength warning: comparison between signed and unsigned integer expressions // should check seekTimeUs < 0 case if (seekTimeUs < 0) { ALOGW("seekTimeUs:%lld < 0", seekTimeUs); seekTimeUs = 0; } #endif size_t size; int64_t seekFrame = seekTimeUs / 20000ll; // 20ms per frame. mCurrentTimeUs = seekFrame * 20000ll; size_t index = seekFrame < 0 ? 0 : seekFrame / 50; if (index >= mOffsetTableLength) { index = mOffsetTableLength - 1; } mOffset = mOffsetTable[index] + (mIsWide ? 9 : 6); for (size_t i = 0; i< seekFrame - index * 50; i++) { status_t err; if ((err = getFrameSizeByOffset(mDataSource, mOffset, mIsWide, &size)) != OK) { return err; } mOffset += size; } } uint8_t header; ssize_t n = mDataSource->readAt(mOffset, &header, 1); if (n < 1) { return ERROR_END_OF_STREAM; } #ifdef MTK_AOSP_ENHANCEMENT int count = 0; while(header & 0x83) { if ((count % 10) == 0) SXLOGW("AMRSource::read--Frame head error,skip until to find an valid one count %d",count); mOffset++; count++; if (count>320) { SXLOGW("getFrameSizeByOffset--can not find the correct frame header in 64 byte"); return ERROR_END_OF_STREAM; } n = mDataSource->readAt(mOffset, &header, 1); if (n < 1) { return ERROR_END_OF_STREAM; } } #else if (header & 0x83) { // Padding bits must be 0. ALOGE("padding bits must be 0, header is 0x%02x", header); return ERROR_MALFORMED; } #endif unsigned FT = (header >> 3) & 0x0f; size_t frameSize = getFrameSize(mIsWide, FT); if (frameSize == 0) { return ERROR_MALFORMED; } MediaBuffer *buffer; status_t err = mGroup->acquire_buffer(&buffer); if (err != OK) { return err; } n = mDataSource->readAt(mOffset, buffer->data(), frameSize); if (n != (ssize_t)frameSize) { buffer->release(); buffer = NULL; return ERROR_IO; } buffer->set_range(0, frameSize); buffer->meta_data()->setInt64(kKeyTime, mCurrentTimeUs); buffer->meta_data()->setInt32(kKeyIsSyncFrame, 1); mOffset += frameSize; mCurrentTimeUs += 20000; // Each frame is 20ms *out = buffer; return OK; }
AMRExtractor::AMRExtractor(const sp<DataSource> &source) : mDataSource(source), mInitCheck(NO_INIT), mOffsetTableLength(0) { String8 mimeType; float confidence; if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) { return; } mIsWide = (mimeType == MEDIA_MIMETYPE_AUDIO_AMR_WB); mMeta = new MetaData; mMeta->setCString( kKeyMIMEType, mIsWide ? MEDIA_MIMETYPE_AUDIO_AMR_WB : MEDIA_MIMETYPE_AUDIO_AMR_NB); mMeta->setInt32(kKeyChannelCount, 1); mMeta->setInt32(kKeySampleRate, mIsWide ? 16000 : 8000); off64_t offset = mIsWide ? 9 : 6; off64_t streamSize; size_t frameSize, numFrames = 0; int64_t duration = 0; #ifdef MTK_AOSP_ENHANCEMENT status_t ret = 0; bool streamingFlag = mDataSource->flags() & DataSource::kIsCachingDataSource; char *pData = new char [Buffer_Count_Readed]; ssize_t dataLen = 0; size_t dataOffset = 0; SXLOGD("AMRExtractor--is streaming flag=%d, pData:0x%x", streamingFlag, pData); #endif if (mDataSource->getSize(&streamSize) == OK) { while (offset < streamSize) { #ifdef MTK_AOSP_ENHANCEMENT if (pData) { if (dataLen==0) { dataLen = mDataSource->readAt(offset, (void *)pData, Buffer_Count_Readed); if (dataLen < 0) { return; } dataOffset = 0; } ret = getFrameSizeByOffset_MMIO((uint8_t *)pData, dataLen, dataOffset, offset, mIsWide, &frameSize); if (ret==NO_MEMORY) { dataLen = 0; continue; } }else { ret = getFrameSizeByOffset(source, offset, mIsWide, &frameSize); } if (ret==ERROR_END_OF_STREAM) { break; }else if(ret!=OK) { if (pData) delete [] pData; pData = 0; SXLOGD("AMRExtractor--getFrameSizeByOffset is not ok!"); return; } #else if (getFrameSizeByOffset(source, offset, mIsWide, &frameSize) != OK) { return; } #endif if ((numFrames % 50 == 0) && (numFrames / 50 < OFFSET_TABLE_LEN)) { CHECK_EQ(mOffsetTableLength, numFrames / 50); mOffsetTable[mOffsetTableLength] = offset - (mIsWide ? 9: 6); mOffsetTableLength ++; } #ifdef MTK_AOSP_ENHANCEMENT else if(streamingFlag&&(numFrames>=50*OFFSET_TABLE_LEN)) { duration += 20000*(streamSize - offset)/((offset - (mIsWide ? 9: 6))/(off64_t)numFrames); SXLOGV("AMRExtractor--end duration=%lld, frame size = %lld", duration, (offset - (mIsWide ? 9: 6))/(off64_t)numFrames); break; } #endif offset += frameSize; duration += 20000; // Each frame is 20ms numFrames ++; } mMeta->setInt64(kKeyDuration, duration); } #ifdef MTK_AOSP_ENHANCEMENT if (pData) delete [] pData; pData = 0; SXLOGD("AMRExtractor--constructor out -"); #endif mInitCheck = OK; }