int getRIFFSize(u8* riff, int bufsize) { const int firstChunkOffset = 12; int fmtChunkOffset = getChunkOffset(riff, bufsize, FMT_CHUNK_MAGIC, firstChunkOffset); int dataChunkOffset = getChunkOffset(riff, bufsize, DATA_CHUNK_MAGIC, firstChunkOffset); if (fmtChunkOffset < 0 || dataChunkOffset < 0) return 0; int dataSize = getBufValue((int*)riff, dataChunkOffset + 4); return dataSize + dataChunkOffset + 8; }
int getRIFFendSample(u8* riff, int bufsize) { const int firstChunkOffset = 12; int dataChunkOffset = getChunkOffset(riff, bufsize, DATA_CHUNK_MAGIC, firstChunkOffset); if (dataChunkOffset < 0) return -1; int factChunkOffset = getChunkOffset(riff, dataChunkOffset, FACT_CHUNK_MAGIC, firstChunkOffset); if (factChunkOffset >= 0) { int factChunkSize = getBufValue((int*)riff, factChunkOffset + 4); if (factChunkSize >= 8) { int endSample = getBufValue((int*)riff, factChunkOffset + 8); return endSample; } } return -1; }
int getRIFFChannels(u8* riff, int bufsize) { const int firstChunkOffset = 12; int fmtChunkOffset = getChunkOffset(riff, bufsize, FMT_CHUNK_MAGIC, firstChunkOffset); if (fmtChunkOffset < 0) return 0; u16 channel = getBufValue((u16*)riff, fmtChunkOffset + 0x0a); return channel; }
int getRIFFLoopNum(u8* riff, int bufsize, int *startsample, int *endsample) { const int firstChunkOffset = 12; int dataChunkOffset = getChunkOffset(riff, bufsize, DATA_CHUNK_MAGIC, firstChunkOffset); if (dataChunkOffset < 0) return 0; int smplChunkOffset = getChunkOffset(riff, dataChunkOffset, SMPL_CHUNK_MAGIC, firstChunkOffset); if (smplChunkOffset < 0) return 0; int factChunkOffset = getChunkOffset(riff, dataChunkOffset, FACT_CHUNK_MAGIC, firstChunkOffset); int atracSampleOffset = 0; if (factChunkOffset >= 0) { int factChunkSize = getBufValue((int*)riff, factChunkOffset + 4); if (factChunkSize >= 8) { atracSampleOffset = getBufValue((int*)riff, factChunkOffset + 12); } } int smplChunkSize = getBufValue((int*)riff, smplChunkOffset + 4); int checkNumLoops = getBufValue((int*)riff, smplChunkOffset + 36); if (smplChunkSize >= 36 + checkNumLoops * 24) { // find loop info, simple return -1 now for endless loop int numLoops = checkNumLoops; int loopInfoAddr = smplChunkOffset + 44; int loopcounts = (numLoops > 1) ? -1 : 0; for (int i = 0; i < 1; i++) { if (startsample) *startsample = getBufValue((int*)riff, loopInfoAddr + 8) - atracSampleOffset; if (endsample) *endsample = getBufValue((int*)riff, loopInfoAddr + 12) - atracSampleOffset; int playcount = getBufValue((int*)riff, loopInfoAddr + 20); if (playcount != 1) loopcounts = -1; loopInfoAddr += 24; } return loopcounts; } return 0; }
status_t SampleIterator::seekTo(uint32_t sampleIndex) { ALOGV("seekTo(%d)", sampleIndex); if (sampleIndex >= mTable->mNumSampleSizes) { return ERROR_END_OF_STREAM; } if (mTable->mSampleToChunkOffset < 0 || mTable->mChunkOffsetOffset < 0 || mTable->mSampleSizeOffset < 0 || mTable->mTimeToSampleCount == 0) { return ERROR_MALFORMED; } if (mInitialized && mCurrentSampleIndex == sampleIndex) { return OK; } if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) { reset(); } if (sampleIndex >= mStopChunkSampleIndex) { status_t err; if ((err = findChunkRange(sampleIndex)) != OK) { ALOGE("findChunkRange failed"); return err; } } CHECK(sampleIndex < mStopChunkSampleIndex); uint32_t chunk = (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk + mFirstChunk; if (!mInitialized || chunk != mCurrentChunkIndex) { mCurrentChunkIndex = chunk; status_t err; if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) { ALOGE("getChunkOffset return error"); return err; } mCurrentChunkSampleSizes.clear(); uint32_t firstChunkSampleIndex = mFirstChunkSampleIndex + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk); for (uint32_t i = 0; i < mSamplesPerChunk; ++i) { size_t sampleSize; if ((err = getSampleSizeDirect( firstChunkSampleIndex + i, &sampleSize)) != OK) { ALOGE("getSampleSizeDirect return error"); return err; } mCurrentChunkSampleSizes.push(sampleSize); } } uint32_t chunkRelativeSampleIndex = (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk; mCurrentSampleOffset = mCurrentChunkOffset; for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) { mCurrentSampleOffset += mCurrentChunkSampleSizes[i]; } mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex]; if (sampleIndex < mTTSSampleIndex) { mTimeToSampleIndex = 0; mTTSSampleIndex = 0; mTTSSampleTime = 0; mTTSCount = 0; mTTSDuration = 0; } status_t err; if ((err = findSampleTimeAndDuration( sampleIndex, &mCurrentSampleTime, &mCurrentSampleDuration)) != OK) { ALOGE("findSampleTime return error"); return err; } mCurrentSampleIndex = sampleIndex; mInitialized = true; return OK; }
int convertRIFFtoOMA(u8* riff, int riffSize, u8** outputStream, int* readSize) { const int firstChunkOffset = 12; int fmtChunkOffset = getChunkOffset(riff, riffSize, FMT_CHUNK_MAGIC, firstChunkOffset); if (fmtChunkOffset < 0) { *outputStream = 0; return 0; } u8 codecId = getBufValue(riff, fmtChunkOffset + 0x30); u8 headerCode0 = getBufValue(riff, fmtChunkOffset + 0x31); u8 headerCode1 = getBufValue(riff, fmtChunkOffset + 0x32); u8 headerCode2 = getBufValue(riff, fmtChunkOffset + 0x33); bool bsupported = false; u16 magic = getBufValue((u16*)riff, fmtChunkOffset + 0x08); if (magic == AT3_MAGIC) { u8 key = getBufValue((u8*)riff, fmtChunkOffset + 0x11); u16 channel = getBufValue((u16*)riff, fmtChunkOffset + 0x0a); switch (key) { case 0x20: { // 66kpbs codecId = 0; headerCode0 = 0x02; headerCode1 = 0x20; headerCode2 = 0x18; } break; case 0x40: { // 132kpbs codecId = 0; headerCode0 = 0x00; headerCode1 = 0x20; headerCode2 = 0x30; } break; default: { // 105kpbs codecId = 0; headerCode0 = 0x00; headerCode1 = 0x20; headerCode2 = 0x26; } break; } if (channel == 2) bsupported = true; else bsupported = false; } else if (magic == AT3_PLUS_MAGIC && headerCode0 == 0x00 && headerCode1 == 0x28) { for (int i = 0; i < atrac3plusradiosize; i++) { if (atrac3plusradio[i] == headerCode2) { bsupported = true; break; } } } if (bsupported == false) { *outputStream = 0; return 0; } int dataChunkOffset = getChunkOffset(riff, riffSize, DATA_CHUNK_MAGIC, firstChunkOffset); if (dataChunkOffset < 0) { *outputStream = 0; return 0; } int dataSize = getBufValue((int*)riff, dataChunkOffset + 4); int datapos = dataChunkOffset + 8; u8* oma = new u8[OMAHeaderSize + dataSize]; int omapos = 0; omapos += getOmaHeader(codecId, headerCode0, headerCode1, headerCode2, oma); WriteBuf(oma, omapos, riff + datapos, dataSize); *outputStream = oma; if (readSize) *readSize = OMAHeaderSize + riffSize - datapos; return omapos; }
status_t SampleIterator::seekTo(uint32_t sampleIndex) { ALOGV("seekTo(%d)", sampleIndex); #ifdef MTK_AOSP_ENHANCEMENT bool isNewChunk = false; #endif if (sampleIndex >= mTable->mNumSampleSizes) { return ERROR_END_OF_STREAM; } if (mTable->mSampleToChunkOffset < 0 || mTable->mChunkOffsetOffset < 0 || mTable->mSampleSizeOffset < 0 || mTable->mTimeToSampleCount == 0) { return ERROR_MALFORMED; } if (mInitialized && mCurrentSampleIndex == sampleIndex) { return OK; } if (!mInitialized || sampleIndex < mFirstChunkSampleIndex) { #ifdef MTK_AOSP_ENHANCEMENT isNewChunk = true; #endif reset(); } if (sampleIndex >= mStopChunkSampleIndex) { #ifdef MTK_AOSP_ENHANCEMENT isNewChunk = true; #endif status_t err; if ((err = findChunkRange(sampleIndex)) != OK) { ALOGE("findChunkRange failed"); return err; } } CHECK(sampleIndex < mStopChunkSampleIndex); uint32_t chunk = (sampleIndex - mFirstChunkSampleIndex) / mSamplesPerChunk + mFirstChunk; if (!mInitialized || chunk != mCurrentChunkIndex) { #ifdef MTK_AOSP_ENHANCEMENT isNewChunk = true; #endif mCurrentChunkIndex = chunk; status_t err; if ((err = getChunkOffset(chunk, &mCurrentChunkOffset)) != OK) { ALOGE("getChunkOffset return error"); return err; } mCurrentChunkSampleSizes.clear(); uint32_t firstChunkSampleIndex = mFirstChunkSampleIndex + mSamplesPerChunk * (mCurrentChunkIndex - mFirstChunk); for (uint32_t i = 0; i < mSamplesPerChunk; ++i) { size_t sampleSize; if ((err = getSampleSizeDirect( firstChunkSampleIndex + i, &sampleSize)) != OK) { ALOGE("getSampleSizeDirect return error"); #ifdef MTK_AOSP_ENHANCEMENT if (err == ERROR_OUT_OF_RANGE) { ALOGW("Sample Index(from stsc) > Sample Count(from stsz), Set mSamplesPerChunk to %d according to stsz", mSamplesPerChunk); mSamplesPerChunk = i; break; } else return err; #else return err; #endif } mCurrentChunkSampleSizes.push(sampleSize); } } uint32_t chunkRelativeSampleIndex = (sampleIndex - mFirstChunkSampleIndex) % mSamplesPerChunk; #ifdef MTK_AOSP_ENHANCEMENT if (!isNewChunk && (sampleIndex == mCurrentSampleIndex + 1) && (chunkRelativeSampleIndex > 0)) { mCurrentSampleOffset += mCurrentChunkSampleSizes[chunkRelativeSampleIndex-1]; } else { #endif mCurrentSampleOffset = mCurrentChunkOffset; for (uint32_t i = 0; i < chunkRelativeSampleIndex; ++i) { mCurrentSampleOffset += mCurrentChunkSampleSizes[i]; } #ifdef MTK_AOSP_ENHANCEMENT } #endif mCurrentSampleSize = mCurrentChunkSampleSizes[chunkRelativeSampleIndex]; if (sampleIndex < mTTSSampleIndex) { mTimeToSampleIndex = 0; mTTSSampleIndex = 0; mTTSSampleTime = 0; mTTSCount = 0; mTTSDuration = 0; } status_t err; if ((err = findSampleTimeAndDuration( sampleIndex, &mCurrentSampleTime, &mCurrentSampleDuration)) != OK) { ALOGE("findSampleTime return error"); return err; } mCurrentSampleIndex = sampleIndex; mInitialized = true; return OK; }