status_t AudioTrackCenter::init() { audio_stream_type_t streamType; if (!mAfFrameCount || !mAfSampleRate) { if (AudioSystem::getOutputFrameCount(&mAfFrameCount, streamType) != NO_ERROR) { SXLOGE("AudioSystem::getOutputFrameCount Fail!!!"); return NO_INIT; } if (AudioSystem::getOutputSamplingRate(&mAfSampleRate, streamType) != NO_ERROR) { SXLOGE("AudioSystem::getOutputSamplingRate Fail!!!"); return NO_INIT; } SXLOGD("init, mAfFrameCount = %d, mAfSampleRate = %d",mAfFrameCount, mAfSampleRate); } return OK; }
AudioVUnlockDL::AudioVUnlockDL() { int32_t ret; ret = pthread_mutex_init(&mVUnlockReadMutex, NULL); if (ret != 0) { SXLOGE("Failed to initialize AudioVUnlockDL mMutex!"); } ret = pthread_mutex_init(&mSRCMutex, NULL); if (ret != 0) { SXLOGE("Failed to initialize AudioVUnlockDL mSRCMutex!"); } mState = VPWStreamIn_CREATED; mReadThreadExit = true; mReadThreadActive = false; mOutputSampleRate = VPW_OUTPUT_SAMPLERATE; mInputSampleRate = 44100; mInChannel = 2; mOutChannel = 0; mpSrcHdl = NULL; mSrcBufLen = 0; mOutFile = 0; mSampleCount_Dump = 0; mInputStandby = true; mStreamOutLatency = 92; mULtime.tv_sec = 0; mULtime.tv_nsec = 0; mDLtime.tv_sec = 0; mNewDLtime.tv_nsec = 0; mNewDLtime.tv_sec = 0; mDLtime.tv_nsec = 0; mStandbyTime.tv_sec = 0; mStandbyTime.tv_nsec = 0; mNeedBlock = false; mGetTime = true; mOutRemaining = 0; mInRemaining = 0; mTempBuf = NULL; mTempBufsz = 0; }
const sp<IATVCtrlService>& ATVCtrl::get_ATVCtrlService_FM() { SXLOGD("get_ATVCtrlService_FM()"); Mutex::Autolock _l(mLock); if (spATVCtrlService.get() == 0 || spATVCtrlClient_FM == NULL) { sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16("media.ATVCtrlService")); if (binder != 0) { break; } SXLOGW("ATVCtrlService not published, waiting..."); usleep(500000); // 0.5 s } while (true); if (spATVCtrlClient_FM == NULL) { spATVCtrlClient_FM = new ATVCtrlClient(); } else { /* if (gATVErrorCallback){ gATVErrorCallback(NO_ERROR); } */ SXLOGD(" spATVCtrlClient_FM exist "); } binder->linkToDeath(spATVCtrlClient_FM); spATVCtrlService = interface_cast<IATVCtrlService>(binder); spATVCtrlService->registerClient_FM(spATVCtrlClient_FM); SXLOGD(" ATVCtrlService is published, or new spATVCtrlClient_FM "); } if (spATVCtrlService == 0) { SXLOGE("no ATVCtrlService!?"); } return spATVCtrlService; }
//#define WRITEOVER void *ReadRoutine(void *hdl) { AudioVUnlockRingBuf *ringBuf_in; AudioVUnlockRingBuf *ringBuf_out; int32_t readAmount; int32_t rwfailcount = 0; AudioVUnlockDL *VInstance = AudioVUnlockDL::getInstance(); char *tempbuffer = new char[VOICE_UNLOCK_RING_BUFFER_SIZE]; char *tempSRCbuffer = new char[6000]; uint32_t dataread = 0; int32_t datawritten = 0; SXLOGD(" [ReadRoutine] start"); // defaut setting of thread init pthread_mutex_lock(&mVUnlockReadMutex); VInstance->mReadThreadExit = false; VInstance->mReadThreadActive = true; pthread_mutex_unlock(&mVUnlockReadMutex); ringBuf_in = (AudioVUnlockRingBuf *) & (VInstance->mRingBufIn); ringBuf_out = (AudioVUnlockRingBuf *) & (VInstance->mRingBufOut); if (VInstance == NULL || ringBuf_in == NULL || ringBuf_out == NULL) { SXLOGD(" [ReadRoutine] Buffer NULL, Exit"); pthread_mutex_lock(&mVUnlockReadMutex); VInstance->mReadThreadExit = true; VInstance->mReadThreadActive = false; pthread_mutex_unlock(&mVUnlockReadMutex); } #ifdef MTK_AUDIO_ADJUST_PRIORITY int result = -1; // if set priority false , force to set priority if (result == -1) { struct sched_param sched_p; sched_getparam(0, &sched_p); sched_p.sched_priority = RTPM_PRIO_AUDIO_I2S; if (0 != sched_setscheduler(0, SCHED_RR, &sched_p)) { SXLOGE("[%s] failed, errno: %d", __func__, errno); } else { sched_p.sched_priority = RTPM_PRIO_AUDIO_I2S; sched_getparam(0, &sched_p); SXLOGD("sched_setscheduler ok, priority: %d", sched_p.sched_priority); } } #endif while (!VInstance->mReadThreadExit) { // Clear DL time if remaining data is pushed. if (VInstance->mDLtime.tv_nsec != 0 && VInstance->mNewDLtime.tv_sec != 0) { if (VInstance->mInRemaining == 0 && VInstance->mOutRemaining == 0) { VInstance->mDLtime.tv_sec = 0; VInstance->mDLtime.tv_nsec = 0; //SXLOGV("[ReadRoutine] All Data from last playback pushed"); } } // switch DL time to new DL time if (VInstance->mDLtime.tv_sec == 0 && VInstance->mNewDLtime.tv_sec != 0) { VInstance->mDLtime.tv_sec = VInstance->mNewDLtime.tv_sec ; VInstance->mDLtime.tv_nsec = VInstance->mNewDLtime.tv_nsec; VInstance->mNewDLtime.tv_sec = 0; VInstance->mNewDLtime.tv_nsec = 0; SXLOGV("[ReadRoutine] switch to new DL time %d %d", VInstance->mDLtime.tv_sec, VInstance->mDLtime.tv_nsec); } uint32_t readsz = ringBuf_in->GetBufDataSz(); dataread = ringBuf_in->ReadWithoutAdvance(tempbuffer, readsz); if (VInstance->mInRemaining != 0) { dataread = dataread > VInstance->mInRemaining ? VInstance->mInRemaining : dataread; } if (dataread <= 0 || VInstance->mDLtime.tv_sec == 0) // do not read data if mDLtime is ready. { if (VInstance->StreamOutStandBy() && ringBuf_out->GetBufDataSz() == 0) { //SXLOGV("[ReadRoutine] Standby, and all data from last playback is pushed"); VInstance->mDLtime.tv_sec = 0; VInstance->mDLtime.tv_nsec = 0; } //SXLOGV("[ReadRoutine] No data from stream out, sleep"); usleep(30 * 1000); } else { //do SRC uint32_t dataproduced = ringBuf_out->GetBufSpace(); dataproduced = dataproduced > 6000 ? 6000 : dataproduced; int32_t dataConsumed = VInstance->DoSRC((uint8_t *) tempbuffer, &dataread , (uint8_t *) tempSRCbuffer, &dataproduced); #ifdef DUMP_VPW_StreamIn_DATA //VInstance->DumpData(tempSRCbuffer, dataproduced); if (VInstance->mOutFile_1 != NULL) { VInstance->mOutFile_1 = fopen("/sdcard/audio_dump/VPW_SRC.pcm", "ab+"); fwrite(tempSRCbuffer, sizeof(char), dataproduced, VInstance->mOutFile_1); fclose(VInstance->mOutFile_1); } #endif if (dataConsumed > 0) { datawritten = ringBuf_out->Write(tempSRCbuffer, dataproduced); SXLOGV("[ReadRoutine] write to ring out, datawritten %d", datawritten); } else { datawritten = 0; } if (datawritten <= 0) // write fail { rwfailcount++; if (rwfailcount > 100) { SXLOGD("[ReadRoutine] Fail, write fail"); break; } SXLOGD("[ReadRoutine] No space to write, sleep"); usleep(10 * 1000); //10ms } else//advance read pointer according to data actually write to output buffer { ringBuf_in->AdvanceReadPointer((uint32_t)dataConsumed); if (VInstance->mInRemaining != 0) { SXLOGV("[ReadRoutine] last playback in buffer remaining %d", VInstance->mInRemaining); VInstance->mInRemaining -= dataConsumed; VInstance->mOutRemaining += datawritten; } ringBuf_out->SignalBufData(); SXLOGV("[ReadRoutine] advance Read poniter %d " , (uint32_t)dataConsumed); rwfailcount = 0; } } } delete tempbuffer; delete tempSRCbuffer; SXLOGD("[ReadRoutine] exit "); VInstance->ClearState(VPWStreamIn_READ_START); SXLOGD("stop and signal ReadRefFromRing to stop"); ringBuf_out->SignalBufData(); int cnt_val = 50; while ((VInstance->mReadFunctionActive == true) && (cnt_val > 0)) { SXLOGD("[ReadRoutine]Signal ReadRefFromRing to stop and wait (%d) ", cnt_val); cnt_val--; ringBuf_out->SignalBufData(); usleep(1000 * 10); } pthread_mutex_lock(&mVUnlockReadMutex); VInstance->mReadThreadExit = true; VInstance->mReadThreadActive = false; pthread_mutex_unlock(&mVUnlockReadMutex); return 0; }
void MyVorbisExtractor::buildTableOfContents() { off64_t offset = mFirstDataOffset; Page page; ssize_t pageSize; #ifndef MTK_AOSP_ENHANCEMENT while ((pageSize = readPage(offset, &page)) > 0) { #else struct timeval tb,te; gettimeofday(&tb,NULL); while (mTocStarted && ((pageSize = readPage(offset, &page)) > 0)) { if(page.mGranulePosition < 0xFFFFFFFFFFFF) { #endif mTableOfContents.push(); TOCEntry &entry = mTableOfContents.editItemAt(mTableOfContents.size() - 1); entry.mPageOffset = offset; entry.mTimeUs = page.mGranulePosition * 1000000ll / mVi.rate; #ifdef MTK_AOSP_ENHANCEMENT //sleep 100ms for consumes over 2s gettimeofday(&te,NULL); if((te.tv_sec - tb.tv_sec) > 2) { gettimeofday(&tb,NULL); usleep(100000); } } #endif offset += (size_t)pageSize; } // Limit the maximum amount of RAM we spend on the table of contents, // if necessary thin out the table evenly to trim it down to maximum // size. static const size_t kMaxTOCSize = 8192; static const size_t kMaxNumTOCEntries = kMaxTOCSize / sizeof(TOCEntry); size_t numerator = mTableOfContents.size(); if (numerator > kMaxNumTOCEntries) { size_t denom = numerator - kMaxNumTOCEntries; size_t accum = 0; for (ssize_t i = mTableOfContents.size() - 1; i >= 0; --i) { accum += denom; if (accum >= numerator) { mTableOfContents.removeAt(i); accum -= numerator; } } } #ifdef MTK_AOSP_ENHANCEMENT mTocDone = true; #endif } status_t MyVorbisExtractor::verifyHeader( MediaBuffer *buffer, uint8_t type) { const uint8_t *data = (const uint8_t *)buffer->data() + buffer->range_offset(); size_t size = buffer->range_length(); if (size < 7 || data[0] != type || memcmp(&data[1], "vorbis", 6)) { return ERROR_MALFORMED; } ogg_buffer buf; buf.data = (uint8_t *)data; buf.size = size; buf.refcount = 1; buf.ptr.owner = NULL; ogg_reference ref; ref.buffer = &buf; ref.begin = 0; ref.length = size; ref.next = NULL; oggpack_buffer bits; oggpack_readinit(&bits, &ref); CHECK_EQ(oggpack_read(&bits, 8), type); for (size_t i = 0; i < 6; ++i) { oggpack_read(&bits, 8); // skip 'vorbis' } switch (type) { case 1: { #ifndef MTK_AOSP_ENHANCEMENT CHECK_EQ(0, _vorbis_unpack_info(&mVi, &bits)); #else _vorbis_unpack_info(&mVi, &bits);//skip the CHECK #endif mMeta->setData(kKeyVorbisInfo, 0, data, size); mMeta->setInt32(kKeySampleRate, mVi.rate); mMeta->setInt32(kKeyChannelCount, mVi.channels); #ifdef MTK_AOSP_ENHANCEMENT if(mVi.channels > 2) { #ifndef MTK_SWIP_VORBIS SXLOGE("Tremolo does not support multi channel"); return ERROR_UNSUPPORTED; #endif } #endif ALOGV("lower-bitrate = %ld", mVi.bitrate_lower); ALOGV("upper-bitrate = %ld", mVi.bitrate_upper); ALOGV("nominal-bitrate = %ld", mVi.bitrate_nominal); ALOGV("window-bitrate = %ld", mVi.bitrate_window); off64_t size; if (mSource->getSize(&size) == OK) { uint64_t bps = approxBitrate(); if (bps != 0) { mMeta->setInt64(kKeyDuration, size * 8000000ll / bps); } } break; } case 3: { if (0 != _vorbis_unpack_comment(&mVc, &bits)) { return ERROR_MALFORMED; } parseFileMetaData(); break; } case 5: { if (0 != _vorbis_unpack_books(&mVi, &bits)) { return ERROR_MALFORMED; } mMeta->setData(kKeyVorbisBooks, 0, data, size); break; } } return OK; } uint64_t MyVorbisExtractor::approxBitrate() { if (mVi.bitrate_nominal != 0) { return mVi.bitrate_nominal; } return (mVi.bitrate_lower + mVi.bitrate_upper) / 2; } void MyVorbisExtractor::parseFileMetaData() { mFileMeta = new MetaData; #ifdef MTK_AOSP_ENHANCEMENT if(mFileMeta.get() == NULL) return; #endif mFileMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_OGG); for (int i = 0; i < mVc.comments; ++i) { const char *comment = mVc.user_comments[i]; size_t commentLength = mVc.comment_lengths[i]; parseVorbisComment(mFileMeta, comment, commentLength); //ALOGI("comment #%d: '%s'", i + 1, mVc.user_comments[i]); } }