Loading media/libmediaplayerservice/nuplayer/GenericSource.cpp +169 −20 Original line number Diff line number Diff line Loading @@ -40,6 +40,11 @@ namespace android { static int64_t kLowWaterMarkUs = 2000000ll; // 2secs static int64_t kHighWaterMarkUs = 5000000ll; // 5secs static const ssize_t kLowWaterMarkBytes = 40000; static const ssize_t kHighWaterMarkBytes = 200000; NuPlayer::GenericSource::GenericSource( const sp<AMessage> ¬ify, bool uidValid, Loading @@ -55,6 +60,7 @@ NuPlayer::GenericSource::GenericSource( mAudioIsVorbis(false), mIsWidevine(false), mIsSecure(false), mIsStreaming(false), mUIDValid(uidValid), mUID(uid), mFd(-1), Loading @@ -62,7 +68,9 @@ NuPlayer::GenericSource::GenericSource( mMetaDataSize(-1ll), mBitrate(-1ll), mPollBufferingGeneration(0), mPendingReadBufferTypes(0) { mPendingReadBufferTypes(0), mBuffering(false), mPrepareBuffering(false) { resetDataSource(); DataSource::RegisterDefaultSniffers(); } Loading Loading @@ -254,6 +262,20 @@ status_t NuPlayer::GenericSource::initFromDataSource() { } } // Start the selected A/V tracks now before we start buffering. // Widevine sources might re-initialize crypto when starting, if we delay // this to start(), all data buffered during prepare would be wasted. // (We don't actually start reading until start().) if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) { ALOGE("failed to start audio track!"); return UNKNOWN_ERROR; } if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) { ALOGE("failed to start video track!"); return UNKNOWN_ERROR; } mBitrate = totalBitrate; return OK; Loading Loading @@ -352,9 +374,13 @@ void NuPlayer::GenericSource::onPrepareAsync() { mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); } if (mIsWidevine || mCachedSource != NULL) { schedulePollBuffering(); } // For widevine or other cached streaming cases, we need to wait for // enough buffering before reporting prepared. // Note that even when URL doesn't start with widevine://, mIsWidevine // could still be set to true later, if the streaming or file source // is sniffed to be widevine. We don't want to buffer for file source // in that case, so must check the flag now. mIsStreaming = (mIsWidevine || mCachedSource != NULL); } // check initial caching status Loading Loading @@ -397,8 +423,15 @@ void NuPlayer::GenericSource::onPrepareAsync() { | FLAG_CAN_SEEK_FORWARD | FLAG_CAN_SEEK); if (mIsStreaming) { mPrepareBuffering = true; ensureCacheIsFetching(); restartPollBuffering(); } else { notifyPrepared(); } } void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { if (err != OK) { Loading Loading @@ -489,19 +522,17 @@ void NuPlayer::GenericSource::start() { mStopRead = false; if (mAudioTrack.mSource != NULL) { CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK); postReadBuffer(MEDIA_TRACK_TYPE_AUDIO); } if (mVideoTrack.mSource != NULL) { CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK); postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); } setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); mStarted = true; (new AMessage(kWhatStart, id()))->post(); } void NuPlayer::GenericSource::stop() { Loading @@ -526,6 +557,8 @@ void NuPlayer::GenericSource::resume() { // nothing to do, just account for DRM playback status setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); mStarted = true; (new AMessage(kWhatResume, id()))->post(); } void NuPlayer::GenericSource::disconnect() { Loading Loading @@ -558,22 +591,98 @@ void NuPlayer::GenericSource::schedulePollBuffering() { } void NuPlayer::GenericSource::cancelPollBuffering() { mBuffering = false; ++mPollBufferingGeneration; } void NuPlayer::GenericSource::restartPollBuffering() { if (mIsStreaming) { cancelPollBuffering(); onPollBuffering(); } } void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage) { ALOGV("notifyBufferingUpdate: buffering %d%%", percentage); sp<AMessage> msg = dupNotify(); msg->setInt32("what", kWhatBufferingUpdate); msg->setInt32("percentage", percentage); msg->post(); } void NuPlayer::GenericSource::startBufferingIfNecessary() { ALOGV("startBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d", mPrepareBuffering, mBuffering); if (mPrepareBuffering) { return; } if (!mBuffering) { mBuffering = true; ensureCacheIsFetching(); sendCacheStats(); sp<AMessage> notify = dupNotify(); notify->setInt32("what", kWhatPauseOnBufferingStart); notify->post(); } } void NuPlayer::GenericSource::stopBufferingIfNecessary() { ALOGV("stopBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d", mPrepareBuffering, mBuffering); if (mPrepareBuffering) { mPrepareBuffering = false; notifyPrepared(); return; } if (mBuffering) { mBuffering = false; sendCacheStats(); sp<AMessage> notify = dupNotify(); notify->setInt32("what", kWhatResumeOnBufferingEnd); notify->post(); } } void NuPlayer::GenericSource::sendCacheStats() { int32_t kbps = 0; status_t err = UNKNOWN_ERROR; if (mCachedSource != NULL) { err = mCachedSource->getEstimatedBandwidthKbps(&kbps); } else if (mWVMExtractor != NULL) { err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps); } if (err == OK) { sp<AMessage> notify = dupNotify(); notify->setInt32("what", kWhatCacheStats); notify->setInt32("bandwidth", kbps); notify->post(); } } void NuPlayer::GenericSource::ensureCacheIsFetching() { if (mCachedSource != NULL) { mCachedSource->resumeFetchingIfNecessary(); } } void NuPlayer::GenericSource::onPollBuffering() { status_t finalStatus = UNKNOWN_ERROR; int64_t cachedDurationUs = 0ll; int64_t cachedDurationUs = -1ll; ssize_t cachedDataRemaining = -1; if (mCachedSource != NULL) { size_t cachedDataRemaining = cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); if (finalStatus == OK) { Loading @@ -593,12 +702,19 @@ void NuPlayer::GenericSource::onPollBuffering() { = mWVMExtractor->getCachedDurationUs(&finalStatus); } if (finalStatus != OK) { ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus); if (finalStatus == ERROR_END_OF_STREAM) { notifyBufferingUpdate(100); cancelPollBuffering(); } stopBufferingIfNecessary(); return; } else if (cachedDurationUs > 0ll && mDurationUs > 0ll) { int percentage = 100.0 * cachedDurationUs / mDurationUs; } else if (cachedDurationUs >= 0ll) { if (mDurationUs > 0ll) { int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs; int percentage = 100.0 * cachedPosUs / mDurationUs; if (percentage > 100) { percentage = 100; } Loading @@ -606,9 +722,27 @@ void NuPlayer::GenericSource::onPollBuffering() { notifyBufferingUpdate(percentage); } schedulePollBuffering(); ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f); if (cachedDurationUs < kLowWaterMarkUs) { startBufferingIfNecessary(); } else if (cachedDurationUs > kHighWaterMarkUs) { stopBufferingIfNecessary(); } } else if (cachedDataRemaining >= 0) { ALOGV("onPollBuffering: cachedDataRemaining %d bytes", cachedDataRemaining); if (cachedDataRemaining < kLowWaterMarkBytes) { startBufferingIfNecessary(); } else if (cachedDataRemaining > kHighWaterMarkBytes) { stopBufferingIfNecessary(); } } schedulePollBuffering(); } void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { Loading Loading @@ -688,6 +822,14 @@ void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { break; } case kWhatStart: case kWhatResume: { restartPollBuffering(); break; } case kWhatPollBuffering: { int32_t generation; Loading Loading @@ -1201,6 +1343,13 @@ status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs) { if (!mStarted) { setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); } // If currently buffering, post kWhatBufferingEnd first, so that // NuPlayer resumes. Otherwise, if cache hits high watermark // before new polling happens, no one will resume the playback. stopBufferingIfNecessary(); restartPollBuffering(); return OK; } Loading media/libmediaplayerservice/nuplayer/GenericSource.h +11 −2 Original line number Diff line number Diff line Loading @@ -94,16 +94,17 @@ private: kWhatSeek, kWhatReadBuffer, kWhatStopWidevine, kWhatStart, kWhatResume, }; Vector<sp<MediaSource> > mSources; struct Track { size_t mIndex; sp<MediaSource> mSource; sp<AnotherPacketSource> mPackets; }; Vector<sp<MediaSource> > mSources; Track mAudioTrack; int64_t mAudioTimeUs; int64_t mAudioLastDequeueTimeUs; Loading @@ -119,6 +120,7 @@ private: bool mAudioIsVorbis; bool mIsWidevine; bool mIsSecure; bool mIsStreaming; bool mUIDValid; uid_t mUID; sp<IMediaHTTPService> mHTTPService; Loading @@ -143,6 +145,8 @@ private: int64_t mBitrate; int32_t mPollBufferingGeneration; uint32_t mPendingReadBufferTypes; bool mBuffering; bool mPrepareBuffering; mutable Mutex mReadBufferLock; sp<ALooper> mLooper; Loading Loading @@ -194,8 +198,13 @@ private: void schedulePollBuffering(); void cancelPollBuffering(); void restartPollBuffering(); void onPollBuffering(); void notifyBufferingUpdate(int percentage); void startBufferingIfNecessary(); void stopBufferingIfNecessary(); void sendCacheStats(); void ensureCacheIsFetching(); DISALLOW_EVIL_CONSTRUCTORS(GenericSource); }; Loading media/libmediaplayerservice/nuplayer/NuPlayer.cpp +58 −11 Original line number Diff line number Diff line Loading @@ -180,7 +180,9 @@ NuPlayer::NuPlayer() mFlushingVideo(NONE), mResumePending(false), mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), mStarted(false) { mStarted(false), mPaused(false), mPausedByClient(false) { clearFlushComplete(); } Loading Loading @@ -598,6 +600,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } else { onStart(); } mPausedByClient = false; break; } Loading Loading @@ -956,16 +959,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { case kWhatPause: { if (mSource != NULL) { mSource->pause(); } else { ALOGW("pause called when source is gone or not set"); } if (mRenderer != NULL) { mRenderer->pause(); } else { ALOGW("pause called when renderer is gone or not set"); } onPause(); mPausedByClient = true; break; } Loading @@ -988,6 +983,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } void NuPlayer::onResume() { if (!mPaused) { return; } mPaused = false; if (mSource != NULL) { mSource->resume(); } else { Loading Loading @@ -1072,6 +1071,23 @@ void NuPlayer::onStart() { postScanSources(); } void NuPlayer::onPause() { if (mPaused) { return; } mPaused = true; if (mSource != NULL) { mSource->pause(); } else { ALOGW("pause called when source is gone or not set"); } if (mRenderer != NULL) { mRenderer->pause(); } else { ALOGW("pause called when renderer is gone or not set"); } } bool NuPlayer::audioDecoderStillNeeded() { // Audio decoder is no longer needed if it's in shut/shutting down status. return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER)); Loading Loading @@ -1709,18 +1725,49 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { break; } case Source::kWhatPauseOnBufferingStart: { // ignore if not playing if (mStarted && !mPausedByClient) { ALOGI("buffer low, pausing..."); onPause(); } // fall-thru } case Source::kWhatBufferingStart: { notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0); break; } case Source::kWhatResumeOnBufferingEnd: { // ignore if not playing if (mStarted && !mPausedByClient) { ALOGI("buffer ready, resuming..."); onResume(); } // fall-thru } case Source::kWhatBufferingEnd: { notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0); break; } case Source::kWhatCacheStats: { int32_t kbps; CHECK(msg->findInt32("bandwidth", &kbps)); notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps); break; } case Source::kWhatSubtitleData: { sp<ABuffer> buffer; Loading media/libmediaplayerservice/nuplayer/NuPlayer.h +9 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,14 @@ private: bool mStarted; // Actual pause state, either as requested by client or due to buffering. bool mPaused; // Pause state as requested by client. Note that if mPausedByClient is // true, mPaused is always true; if mPausedByClient is false, mPaused could // still become true, when we pause internally due to buffering. bool mPausedByClient; inline const sp<DecoderBase> &getDecoder(bool audio) { return audio ? mAudioDecoder : mVideoDecoder; } Loading Loading @@ -204,6 +212,7 @@ private: void onStart(); void onResume(); void onPause(); bool audioDecoderStillNeeded(); Loading media/libmediaplayerservice/nuplayer/NuPlayerSource.h +3 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ struct NuPlayer::Source : public AHandler { kWhatBufferingUpdate, kWhatBufferingStart, kWhatBufferingEnd, kWhatPauseOnBufferingStart, kWhatResumeOnBufferingEnd, kWhatCacheStats, kWhatSubtitleData, kWhatTimedTextData, kWhatQueueDecoderShutdown, Loading Loading
media/libmediaplayerservice/nuplayer/GenericSource.cpp +169 −20 Original line number Diff line number Diff line Loading @@ -40,6 +40,11 @@ namespace android { static int64_t kLowWaterMarkUs = 2000000ll; // 2secs static int64_t kHighWaterMarkUs = 5000000ll; // 5secs static const ssize_t kLowWaterMarkBytes = 40000; static const ssize_t kHighWaterMarkBytes = 200000; NuPlayer::GenericSource::GenericSource( const sp<AMessage> ¬ify, bool uidValid, Loading @@ -55,6 +60,7 @@ NuPlayer::GenericSource::GenericSource( mAudioIsVorbis(false), mIsWidevine(false), mIsSecure(false), mIsStreaming(false), mUIDValid(uidValid), mUID(uid), mFd(-1), Loading @@ -62,7 +68,9 @@ NuPlayer::GenericSource::GenericSource( mMetaDataSize(-1ll), mBitrate(-1ll), mPollBufferingGeneration(0), mPendingReadBufferTypes(0) { mPendingReadBufferTypes(0), mBuffering(false), mPrepareBuffering(false) { resetDataSource(); DataSource::RegisterDefaultSniffers(); } Loading Loading @@ -254,6 +262,20 @@ status_t NuPlayer::GenericSource::initFromDataSource() { } } // Start the selected A/V tracks now before we start buffering. // Widevine sources might re-initialize crypto when starting, if we delay // this to start(), all data buffered during prepare would be wasted. // (We don't actually start reading until start().) if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) { ALOGE("failed to start audio track!"); return UNKNOWN_ERROR; } if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) { ALOGE("failed to start video track!"); return UNKNOWN_ERROR; } mBitrate = totalBitrate; return OK; Loading Loading @@ -352,9 +374,13 @@ void NuPlayer::GenericSource::onPrepareAsync() { mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); } if (mIsWidevine || mCachedSource != NULL) { schedulePollBuffering(); } // For widevine or other cached streaming cases, we need to wait for // enough buffering before reporting prepared. // Note that even when URL doesn't start with widevine://, mIsWidevine // could still be set to true later, if the streaming or file source // is sniffed to be widevine. We don't want to buffer for file source // in that case, so must check the flag now. mIsStreaming = (mIsWidevine || mCachedSource != NULL); } // check initial caching status Loading Loading @@ -397,8 +423,15 @@ void NuPlayer::GenericSource::onPrepareAsync() { | FLAG_CAN_SEEK_FORWARD | FLAG_CAN_SEEK); if (mIsStreaming) { mPrepareBuffering = true; ensureCacheIsFetching(); restartPollBuffering(); } else { notifyPrepared(); } } void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) { if (err != OK) { Loading Loading @@ -489,19 +522,17 @@ void NuPlayer::GenericSource::start() { mStopRead = false; if (mAudioTrack.mSource != NULL) { CHECK_EQ(mAudioTrack.mSource->start(), (status_t)OK); postReadBuffer(MEDIA_TRACK_TYPE_AUDIO); } if (mVideoTrack.mSource != NULL) { CHECK_EQ(mVideoTrack.mSource->start(), (status_t)OK); postReadBuffer(MEDIA_TRACK_TYPE_VIDEO); } setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); mStarted = true; (new AMessage(kWhatStart, id()))->post(); } void NuPlayer::GenericSource::stop() { Loading @@ -526,6 +557,8 @@ void NuPlayer::GenericSource::resume() { // nothing to do, just account for DRM playback status setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000); mStarted = true; (new AMessage(kWhatResume, id()))->post(); } void NuPlayer::GenericSource::disconnect() { Loading Loading @@ -558,22 +591,98 @@ void NuPlayer::GenericSource::schedulePollBuffering() { } void NuPlayer::GenericSource::cancelPollBuffering() { mBuffering = false; ++mPollBufferingGeneration; } void NuPlayer::GenericSource::restartPollBuffering() { if (mIsStreaming) { cancelPollBuffering(); onPollBuffering(); } } void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage) { ALOGV("notifyBufferingUpdate: buffering %d%%", percentage); sp<AMessage> msg = dupNotify(); msg->setInt32("what", kWhatBufferingUpdate); msg->setInt32("percentage", percentage); msg->post(); } void NuPlayer::GenericSource::startBufferingIfNecessary() { ALOGV("startBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d", mPrepareBuffering, mBuffering); if (mPrepareBuffering) { return; } if (!mBuffering) { mBuffering = true; ensureCacheIsFetching(); sendCacheStats(); sp<AMessage> notify = dupNotify(); notify->setInt32("what", kWhatPauseOnBufferingStart); notify->post(); } } void NuPlayer::GenericSource::stopBufferingIfNecessary() { ALOGV("stopBufferingIfNecessary: mPrepareBuffering=%d, mBuffering=%d", mPrepareBuffering, mBuffering); if (mPrepareBuffering) { mPrepareBuffering = false; notifyPrepared(); return; } if (mBuffering) { mBuffering = false; sendCacheStats(); sp<AMessage> notify = dupNotify(); notify->setInt32("what", kWhatResumeOnBufferingEnd); notify->post(); } } void NuPlayer::GenericSource::sendCacheStats() { int32_t kbps = 0; status_t err = UNKNOWN_ERROR; if (mCachedSource != NULL) { err = mCachedSource->getEstimatedBandwidthKbps(&kbps); } else if (mWVMExtractor != NULL) { err = mWVMExtractor->getEstimatedBandwidthKbps(&kbps); } if (err == OK) { sp<AMessage> notify = dupNotify(); notify->setInt32("what", kWhatCacheStats); notify->setInt32("bandwidth", kbps); notify->post(); } } void NuPlayer::GenericSource::ensureCacheIsFetching() { if (mCachedSource != NULL) { mCachedSource->resumeFetchingIfNecessary(); } } void NuPlayer::GenericSource::onPollBuffering() { status_t finalStatus = UNKNOWN_ERROR; int64_t cachedDurationUs = 0ll; int64_t cachedDurationUs = -1ll; ssize_t cachedDataRemaining = -1; if (mCachedSource != NULL) { size_t cachedDataRemaining = cachedDataRemaining = mCachedSource->approxDataRemaining(&finalStatus); if (finalStatus == OK) { Loading @@ -593,12 +702,19 @@ void NuPlayer::GenericSource::onPollBuffering() { = mWVMExtractor->getCachedDurationUs(&finalStatus); } if (finalStatus != OK) { ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus); if (finalStatus == ERROR_END_OF_STREAM) { notifyBufferingUpdate(100); cancelPollBuffering(); } stopBufferingIfNecessary(); return; } else if (cachedDurationUs > 0ll && mDurationUs > 0ll) { int percentage = 100.0 * cachedDurationUs / mDurationUs; } else if (cachedDurationUs >= 0ll) { if (mDurationUs > 0ll) { int64_t cachedPosUs = getLastReadPosition() + cachedDurationUs; int percentage = 100.0 * cachedPosUs / mDurationUs; if (percentage > 100) { percentage = 100; } Loading @@ -606,9 +722,27 @@ void NuPlayer::GenericSource::onPollBuffering() { notifyBufferingUpdate(percentage); } schedulePollBuffering(); ALOGV("onPollBuffering: cachedDurationUs %.1f sec", cachedDurationUs / 1000000.0f); if (cachedDurationUs < kLowWaterMarkUs) { startBufferingIfNecessary(); } else if (cachedDurationUs > kHighWaterMarkUs) { stopBufferingIfNecessary(); } } else if (cachedDataRemaining >= 0) { ALOGV("onPollBuffering: cachedDataRemaining %d bytes", cachedDataRemaining); if (cachedDataRemaining < kLowWaterMarkBytes) { startBufferingIfNecessary(); } else if (cachedDataRemaining > kHighWaterMarkBytes) { stopBufferingIfNecessary(); } } schedulePollBuffering(); } void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { Loading Loading @@ -688,6 +822,14 @@ void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { break; } case kWhatStart: case kWhatResume: { restartPollBuffering(); break; } case kWhatPollBuffering: { int32_t generation; Loading Loading @@ -1201,6 +1343,13 @@ status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs) { if (!mStarted) { setDrmPlaybackStatusIfNeeded(Playback::PAUSE, 0); } // If currently buffering, post kWhatBufferingEnd first, so that // NuPlayer resumes. Otherwise, if cache hits high watermark // before new polling happens, no one will resume the playback. stopBufferingIfNecessary(); restartPollBuffering(); return OK; } Loading
media/libmediaplayerservice/nuplayer/GenericSource.h +11 −2 Original line number Diff line number Diff line Loading @@ -94,16 +94,17 @@ private: kWhatSeek, kWhatReadBuffer, kWhatStopWidevine, kWhatStart, kWhatResume, }; Vector<sp<MediaSource> > mSources; struct Track { size_t mIndex; sp<MediaSource> mSource; sp<AnotherPacketSource> mPackets; }; Vector<sp<MediaSource> > mSources; Track mAudioTrack; int64_t mAudioTimeUs; int64_t mAudioLastDequeueTimeUs; Loading @@ -119,6 +120,7 @@ private: bool mAudioIsVorbis; bool mIsWidevine; bool mIsSecure; bool mIsStreaming; bool mUIDValid; uid_t mUID; sp<IMediaHTTPService> mHTTPService; Loading @@ -143,6 +145,8 @@ private: int64_t mBitrate; int32_t mPollBufferingGeneration; uint32_t mPendingReadBufferTypes; bool mBuffering; bool mPrepareBuffering; mutable Mutex mReadBufferLock; sp<ALooper> mLooper; Loading Loading @@ -194,8 +198,13 @@ private: void schedulePollBuffering(); void cancelPollBuffering(); void restartPollBuffering(); void onPollBuffering(); void notifyBufferingUpdate(int percentage); void startBufferingIfNecessary(); void stopBufferingIfNecessary(); void sendCacheStats(); void ensureCacheIsFetching(); DISALLOW_EVIL_CONSTRUCTORS(GenericSource); }; Loading
media/libmediaplayerservice/nuplayer/NuPlayer.cpp +58 −11 Original line number Diff line number Diff line Loading @@ -180,7 +180,9 @@ NuPlayer::NuPlayer() mFlushingVideo(NONE), mResumePending(false), mVideoScalingMode(NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW), mStarted(false) { mStarted(false), mPaused(false), mPausedByClient(false) { clearFlushComplete(); } Loading Loading @@ -598,6 +600,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } else { onStart(); } mPausedByClient = false; break; } Loading Loading @@ -956,16 +959,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { case kWhatPause: { if (mSource != NULL) { mSource->pause(); } else { ALOGW("pause called when source is gone or not set"); } if (mRenderer != NULL) { mRenderer->pause(); } else { ALOGW("pause called when renderer is gone or not set"); } onPause(); mPausedByClient = true; break; } Loading @@ -988,6 +983,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } void NuPlayer::onResume() { if (!mPaused) { return; } mPaused = false; if (mSource != NULL) { mSource->resume(); } else { Loading Loading @@ -1072,6 +1071,23 @@ void NuPlayer::onStart() { postScanSources(); } void NuPlayer::onPause() { if (mPaused) { return; } mPaused = true; if (mSource != NULL) { mSource->pause(); } else { ALOGW("pause called when source is gone or not set"); } if (mRenderer != NULL) { mRenderer->pause(); } else { ALOGW("pause called when renderer is gone or not set"); } } bool NuPlayer::audioDecoderStillNeeded() { // Audio decoder is no longer needed if it's in shut/shutting down status. return ((mFlushingAudio != SHUT_DOWN) && (mFlushingAudio != SHUTTING_DOWN_DECODER)); Loading Loading @@ -1709,18 +1725,49 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { break; } case Source::kWhatPauseOnBufferingStart: { // ignore if not playing if (mStarted && !mPausedByClient) { ALOGI("buffer low, pausing..."); onPause(); } // fall-thru } case Source::kWhatBufferingStart: { notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_START, 0); break; } case Source::kWhatResumeOnBufferingEnd: { // ignore if not playing if (mStarted && !mPausedByClient) { ALOGI("buffer ready, resuming..."); onResume(); } // fall-thru } case Source::kWhatBufferingEnd: { notifyListener(MEDIA_INFO, MEDIA_INFO_BUFFERING_END, 0); break; } case Source::kWhatCacheStats: { int32_t kbps; CHECK(msg->findInt32("bandwidth", &kbps)); notifyListener(MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps); break; } case Source::kWhatSubtitleData: { sp<ABuffer> buffer; Loading
media/libmediaplayerservice/nuplayer/NuPlayer.h +9 −0 Original line number Diff line number Diff line Loading @@ -177,6 +177,14 @@ private: bool mStarted; // Actual pause state, either as requested by client or due to buffering. bool mPaused; // Pause state as requested by client. Note that if mPausedByClient is // true, mPaused is always true; if mPausedByClient is false, mPaused could // still become true, when we pause internally due to buffering. bool mPausedByClient; inline const sp<DecoderBase> &getDecoder(bool audio) { return audio ? mAudioDecoder : mVideoDecoder; } Loading Loading @@ -204,6 +212,7 @@ private: void onStart(); void onResume(); void onPause(); bool audioDecoderStillNeeded(); Loading
media/libmediaplayerservice/nuplayer/NuPlayerSource.h +3 −0 Original line number Diff line number Diff line Loading @@ -48,6 +48,9 @@ struct NuPlayer::Source : public AHandler { kWhatBufferingUpdate, kWhatBufferingStart, kWhatBufferingEnd, kWhatPauseOnBufferingStart, kWhatResumeOnBufferingEnd, kWhatCacheStats, kWhatSubtitleData, kWhatTimedTextData, kWhatQueueDecoderShutdown, Loading