Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 66d02344 authored by Steve Kondik's avatar Steve Kondik
Browse files

nuplayer: Add cached lookup of track duration

 * After a seek in an HTTP source (such as Play Music), the duration
   ends up as zero due to multiple pending fetches.
 * This has a nasty side effect of breaking audio effects connected
   to the global mix (visualizer) after an offload fallback as the
   deep buffer stream wasn't selected either.
 * Cache the last known good duration and use it if the extractor
   isn't able to get it.

Change-Id: I65f60323959455ec1ce45ae88b821d4227eeb14d
parent 9d18eef0
Loading
Loading
Loading
Loading
+38 −5
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ NuPlayer::GenericSource::GenericSource(
      mFetchSubtitleDataGeneration(0),
      mFetchTimedTextDataGeneration(0),
      mDurationUs(0ll),
      mCachedDurationUs(0ll),
      mAudioIsVorbis(false),
      mIsWidevine(false),
      mIsSecure(false),
@@ -92,6 +93,7 @@ void NuPlayer::GenericSource::resetDataSource() {
    mDrmManagerClient = NULL;
    mStarted = false;
    mStopRead = true;
    mInitialSeekTime = -1;
}

status_t NuPlayer::GenericSource::setDataSource(
@@ -593,6 +595,10 @@ void NuPlayer::GenericSource::start() {
    setDrmPlaybackStatusIfNeeded(Playback::START, getLastReadPosition() / 1000);
    mStarted = true;

    if (mInitialSeekTime > 0) {
        doSeek(mInitialSeekTime);
    }

    (new AMessage(kWhatStart, id()))->post();
}

@@ -737,21 +743,25 @@ void NuPlayer::GenericSource::ensureCacheIsFetching() {
    }
}

void NuPlayer::GenericSource::onPollBuffering() {
status_t NuPlayer::GenericSource::getCachedDuration(
        int64_t *cachedDurationUs, size_t *remaining) {
    status_t finalStatus = UNKNOWN_ERROR;
    int64_t cachedDurationUs = -1ll;
    ssize_t cachedDataRemaining = -1;

    ALOGW_IF(mWVMExtractor != NULL && mCachedSource != NULL,
            "WVMExtractor and NuCachedSource both present");

    if (mWVMExtractor != NULL) {
        cachedDurationUs =
        *cachedDurationUs =
                mWVMExtractor->getCachedDurationUs(&finalStatus);
    } else if (mCachedSource != NULL) {
        cachedDataRemaining =
                mCachedSource->approxDataRemaining(&finalStatus);

        if (remaining != 0) {
            *remaining = cachedDataRemaining;
        }

        if (finalStatus == OK) {
            off64_t size;
            int64_t bitrate = 0ll;
@@ -761,11 +771,29 @@ void NuPlayer::GenericSource::onPollBuffering() {
                bitrate = mBitrate;
            }
            if (bitrate > 0) {
                cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
                *cachedDurationUs = cachedDataRemaining * 8000000ll / bitrate;
            }
        } else if (mDurationUs > 0) {
            *cachedDurationUs = mDurationUs;
            return OK;
        }
    }

    if (*cachedDurationUs > 0) {
        mCachedDurationUs = *cachedDurationUs;
    } else {
        *cachedDurationUs = mCachedDurationUs;
    }

    ALOGV("getCachedDuration = %lld", *cachedDurationUs);
    return finalStatus;
}

void NuPlayer::GenericSource::onPollBuffering() {
    int64_t cachedDurationUs = 0ll;
    size_t cachedDataRemaining = 0;
    status_t finalStatus = getCachedDuration(&cachedDurationUs, &cachedDataRemaining);

    if (finalStatus != OK) {
        ALOGV("onPollBuffering: EOS (finalStatus = %d)", finalStatus);

@@ -1396,7 +1424,12 @@ status_t NuPlayer::GenericSource::doSeek(int64_t seekTimeUs) {
    // If the Widevine source is stopped, do not attempt to read any
    // more buffers.
    if (mStopRead) {
        if (mIsWidevine) {
            return INVALID_OPERATION;
        } else if (mInitialSeekTime == -1) {
            mInitialSeekTime = seekTimeUs;
            return OK;
        }
    }
    if (mVideoTrack.mSource != NULL) {
        int64_t actualTimeUs;
+4 −0
Original line number Diff line number Diff line
@@ -72,6 +72,8 @@ struct NuPlayer::GenericSource : public NuPlayer::Source {

    virtual status_t setBuffers(bool audio, Vector<MediaBuffer *> &buffers);

    virtual status_t getCachedDuration(int64_t *durationUs, size_t *cachedDataRemaining = 0);

protected:
    virtual ~GenericSource();

@@ -118,6 +120,7 @@ private:
    int32_t mFetchSubtitleDataGeneration;
    int32_t mFetchTimedTextDataGeneration;
    int64_t mDurationUs;
    int64_t mCachedDurationUs;
    bool mAudioIsVorbis;
    bool mIsWidevine;
    bool mIsSecure;
@@ -140,6 +143,7 @@ private:
    sp<DecryptHandle> mDecryptHandle;
    bool mStarted;
    bool mStopRead;
    int64_t mInitialSeekTime;
    String8 mContentType;
    AString mSniffedMIME;
    off64_t mMetaDataSize;
+7 −0
Original line number Diff line number Diff line
@@ -1106,7 +1106,14 @@ void NuPlayer::onStart() {
        flags |= Renderer::FLAG_REAL_TIME;
    }

    int64_t duration = 0ll;
    sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */);
    if (audioMeta.get() && (
            !audioMeta->findInt64(kKeyDuration, &duration) || duration == 0)) {
        mSource->getCachedDuration(&duration);
        audioMeta->setInt64(kKeyDuration, duration);
    }

    audio_stream_type_t streamType = AUDIO_STREAM_MUSIC;
    if (mAudioSink != NULL) {
        streamType = mAudioSink->getAudioStreamType();
+1 −1
Original line number Diff line number Diff line
@@ -461,7 +461,7 @@ bool NuPlayer::Decoder::handleAnOutputBuffer() {
            int64_t durationUs;
            bool hasVideo = (mSource->getFormat(false /* audio */) != NULL);
            if (!hasVideo &&
                    mSource->getDuration(&durationUs) == OK &&
                    mSource->getCachedDuration(&durationUs) == OK &&
                    durationUs
                        > AUDIO_SINK_MIN_DEEP_BUFFER_DURATION_US) {
                flags = AUDIO_OUTPUT_FLAG_DEEP_BUFFER;
+4 −0
Original line number Diff line number Diff line
@@ -120,6 +120,10 @@ struct NuPlayer::Source : public AHandler {

    virtual int64_t getServerTimeoutUs();

    virtual status_t getCachedDuration(int64_t *durationUs) {
        return getDuration(durationUs);
    }

protected:
    virtual ~Source() {}