ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) { CHECK_LE(size, (size_t)mHighwaterThresholdBytes); LOGV("readInternal offset %lld size %d", offset, size); Mutex::Autolock autoLock(mLock); if (!mFetching) { mLastAccessPos = offset; restartPrefetcherIfNecessary_l( false, // ignoreLowWaterThreshold true); // force } if (offset < mCacheOffset || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) { static const off64_t kPadding = (flags() & kIsLocalDataSource)?0:256 * 1024; // In the presence of multiple decoded streams, once of them will // trigger this seek request, the other one will request data "nearby" // soon, adjust the seek position so that that subsequent request // does not trigger another seek. off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0; seekInternal_l(seekOffset); } size_t delta = offset - mCacheOffset; if (mFinalStatus != OK) { if (delta >= mCache->totalSize()) { return mFinalStatus; } size_t avail = mCache->totalSize() - delta; if (avail > size) { avail = size; } mCache->copy(delta, data, avail); return avail; } if (offset + size <= mCacheOffset + mCache->totalSize()) { mCache->copy(delta, data, size); return size; } LOGV("deferring read"); if (!mFetching) { mLastAccessPos = offset; restartPrefetcherIfNecessary_l(true); } return -EAGAIN; }
void NuCachedSource2::onFetch() { LOGV("onFetch"); if (mFinalStatus != OK) { LOGV("EOS reached, done prefetching for now"); mFetching = false; } bool keepAlive = !mFetching && !mSuspended && mFinalStatus == OK && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs; if (mFetching || keepAlive) { if (keepAlive) { LOGI("Keep alive"); } fetchInternal(); mLastFetchTimeUs = ALooper::GetNowUs(); if (mFetching && mCache->totalSize() >= kHighWaterThreshold) { LOGI("Cache full, done prefetching for now"); mFetching = false; } } else if (!mSuspended) { Mutex::Autolock autoLock(mLock); restartPrefetcherIfNecessary_l(); } (new AMessage(kWhatFetchMore, mReflector->id()))->post( mFetching ? 0 : 100000ll); }
void NuCachedSource2::onFetch() { LOGV("onFetch"); if (mFinalStatus != OK && mNumRetriesLeft == 0) { LOGV("EOS reached, done prefetching for now"); mFetching = false; } bool keepAlive = !mFetching && mFinalStatus == OK && mKeepAliveIntervalUs > 0 && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs; if (mFetching || keepAlive) { if (keepAlive) { LOGI("Keep alive"); } fetchInternal(); mLastFetchTimeUs = ALooper::GetNowUs(); if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) { LOGI("Cache full, done prefetching for now"); mFetching = false; if (mDisconnectAtHighwatermark && (mSource->flags() & DataSource::kIsHTTPBasedSource)) { LOGV("Disconnecting at high watermark"); static_cast<HTTPBase *>(mSource.get())->disconnect(); } if (mFetchMoreCount > 1) { mFetchMoreCount--; return; } } } else { Mutex::Autolock autoLock(mLock); restartPrefetcherIfNecessary_l(); } int64_t delayUs; if (mFetching) { if (mFinalStatus != OK && mNumRetriesLeft > 0) { // We failed this time and will try again in 3 seconds. delayUs = 3000000ll; } else { delayUs = 0; } } else { delayUs = 100000ll; } (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs); }
ssize_t NuCachedSource2::readAt(off64_t offset, void *data, size_t size) { Mutex::Autolock autoSerializer(mSerializer); LOGV("readAt offset %lld, size %d", offset, size); Mutex::Autolock autoLock(mLock); // If the request can be completely satisfied from the cache, do so. if (offset >= mCacheOffset && offset + size <= mCacheOffset + mCache->totalSize()) { size_t delta = offset - mCacheOffset; mCache->copy(delta, data, size); mLastAccessPos = offset + size; restartPrefetcherIfNecessary_l(); return size; } sp<AMessage> msg = new AMessage(kWhatRead, mReflector->id()); msg->setInt64("offset", offset); msg->setPointer("data", data); msg->setSize("size", size); CHECK(mAsyncResult == NULL); msg->post(); while (mAsyncResult == NULL) { mCondition.wait(mLock); } int32_t result; CHECK(mAsyncResult->findInt32("result", &result)); mAsyncResult.clear(); if (result > 0) { mLastAccessPos = offset + result; } return (ssize_t)result; }
void NuCachedSource2::resumeFetchingIfNecessary() { Mutex::Autolock autoLock(mLock); restartPrefetcherIfNecessary_l(true /* ignore low water threshold */); }
void NuCachedSource2::onFetch() { ALOGV("onFetch"); if (mFinalStatus != OK && mNumRetriesLeft == 0) { ALOGV("EOS reached, done prefetching for now"); mFetching = false; } bool keepAlive = !mFetching && mFinalStatus == OK && mKeepAliveIntervalUs > 0 && ALooper::GetNowUs() >= mLastFetchTimeUs + mKeepAliveIntervalUs; if (mFetching || keepAlive) { if (keepAlive) { ALOGI("Keep alive"); } fetchInternal(); mLastFetchTimeUs = ALooper::GetNowUs(); #ifdef OMAP_ENHANCEMENT if (mMinAccessPos - mCacheOffset > kGrayArea) { size_t maxBytes = mMinAccessPos - mCacheOffset - kGrayArea; size_t actualBytes = mCache->releaseFromStart(maxBytes); mCacheOffset += actualBytes; } #endif if (mFetching && mCache->totalSize() >= mHighwaterThresholdBytes) { ALOGI("Cache full, done prefetching for now"); mFetching = false; if (mDisconnectAtHighwatermark && (mSource->flags() & DataSource::kIsHTTPBasedSource)) { ALOGV("Disconnecting at high watermark"); static_cast<HTTPBase *>(mSource.get())->disconnect(); mFinalStatus = -EAGAIN; } } } else { Mutex::Autolock autoLock(mLock); restartPrefetcherIfNecessary_l(); } int64_t delayUs; if (mFetching) { if (mFinalStatus != OK && mNumRetriesLeft > 0) { // We failed this time and will try again in 3 seconds. delayUs = 3000000ll; } else { delayUs = 0; } } else { delayUs = 100000ll; } (new AMessage(kWhatFetchMore, mReflector->id()))->post(delayUs); }
ssize_t NuCachedSource2::readInternal(off64_t offset, void *data, size_t size) { CHECK_LE(size, (size_t)mHighwaterThresholdBytes); ALOGV("readInternal offset %lld size %zu", (long long)offset, size); Mutex::Autolock autoLock(mLock); // If we're disconnecting, return EOS and don't access *data pointer. // data could be on the stack of the caller to NuCachedSource2::readAt(), // which may have exited already. if (mDisconnecting) { return ERROR_END_OF_STREAM; } if (!mFetching) { mLastAccessPos = offset; restartPrefetcherIfNecessary_l( false, // ignoreLowWaterThreshold true); // force } if (offset < mCacheOffset || offset >= (off64_t)(mCacheOffset + mCache->totalSize())) { static const off64_t kPadding = 256 * 1024; // In the presence of multiple decoded streams, once of them will // trigger this seek request, the other one will request data "nearby" // soon, adjust the seek position so that that subsequent request // does not trigger another seek. off64_t seekOffset = (offset > kPadding) ? offset - kPadding : 0; seekInternal_l(seekOffset); } size_t delta = offset - mCacheOffset; if (mFinalStatus != OK && mNumRetriesLeft == 0) { if (delta >= mCache->totalSize()) { return mFinalStatus; } size_t avail = mCache->totalSize() - delta; if (avail > size) { avail = size; } mCache->copy(delta, data, avail); return avail; } if (offset + size <= mCacheOffset + mCache->totalSize()) { mCache->copy(delta, data, size); return size; } ALOGV("deferring read"); return -EAGAIN; }