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

Commit 96eb1543 authored by Surajit Podder's avatar Surajit Podder Committed by Steve Kondik
Browse files

NuPlayer: Buffering improvements for http progressive playback

Added changes for
* Buffering preroll till high watermark in preparing state
* Reduce buffering poll delay to 100ms from 1sec in underrun

CRs-Fixed: 776424
Change-Id: Ide155fd5af8786978532ecbd5970bc0871c55186
(cherry picked from commit 215134952980d10633966fd04f96c0f69b24637b)
parent 17c37877
Loading
Loading
Loading
Loading
+65 −6
Original line number Diff line number Diff line
@@ -41,6 +41,11 @@
#include "../../libstagefright/include/FLACDecoder.h"
#endif

static int64_t kLowWaterMarkUs = 2000000ll;  // 2secs
static int64_t kHighWaterMarkUs = 5000000ll;  // 5secs
static const size_t kLowWaterMarkBytes = 40000;
static const size_t kHighWaterMarkBytes = 200000;

namespace android {

NuPlayer::GenericSource::GenericSource(
@@ -61,7 +66,9 @@ NuPlayer::GenericSource::GenericSource(
      mBitrate(-1ll),
      mPollBufferingGeneration(0),
      mPendingReadBufferTypes(0),
      mStartAfterSuspended(false) {
      mStartAfterSuspended(false),
      mPrepareState(STATE_UNPREPARED),
      mPollBufferDelayUs(100000ll) {
    resetDataSource();
    DataSource::RegisterDefaultSniffers();
}
@@ -97,6 +104,8 @@ status_t NuPlayer::GenericSource::setDataSource(
        mUriHeaders = *headers;
    }

    setPrepareState(STATE_UNPREPARED);

    // delay data source creation to prepareAsync() to avoid blocking
    // the calling thread in setDataSource for any significant time.
    return OK;
@@ -420,7 +429,12 @@ void NuPlayer::GenericSource::onPrepareAsync() {
            | FLAG_CAN_SEEK_FORWARD
            | FLAG_CAN_SEEK);

    notifyPrepared();
    if ((mWVMExtractor == NULL && mCachedSource == NULL) ||
        mPrepareState == STATE_UNPREPARED_EOS) {
        setPrepareState(STATE_PREPARED);
    } else {
        setPrepareState(STATE_PREPARING);
    }
}

void NuPlayer::GenericSource::notifyPreparedAndCleanup(status_t err) {
@@ -589,7 +603,7 @@ status_t NuPlayer::GenericSource::feedMoreTSData() {
void NuPlayer::GenericSource::schedulePollBuffering() {
    sp<AMessage> msg = new AMessage(kWhatPollBuffering, id());
    msg->setInt32("generation", mPollBufferingGeneration);
    msg->post(1000000ll);
    msg->post(mPollBufferDelayUs);
}

void NuPlayer::GenericSource::cancelPollBuffering() {
@@ -605,13 +619,26 @@ void NuPlayer::GenericSource::notifyBufferingUpdate(int percentage,
    msg->post();
}

status_t NuPlayer::GenericSource::getCachedDuration(int64_t *cachedDurationUs) {
void NuPlayer::GenericSource::setPrepareState(PrepareState state) {
    mPrepareState = state;
    if (mPrepareState == STATE_PREPARED) {
        notifyPrepared();
    }
}

status_t NuPlayer::GenericSource::getCachedDuration(int64_t *cachedDurationUs,
        size_t *remaining) {
    status_t finalStatus = UNKNOWN_ERROR;
    size_t cachedDataRemaining = 0;

    if (mCachedSource != NULL) {
        size_t cachedDataRemaining =
        cachedDataRemaining =
                mCachedSource->approxDataRemaining(&finalStatus);

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

        if (finalStatus == OK) {
            off64_t size;
            int64_t bitrate = 0ll;
@@ -644,7 +671,16 @@ status_t NuPlayer::GenericSource::getCachedDuration(int64_t *cachedDurationUs) {

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

    if (finalStatus != OK) {
        if (mPrepareState == STATE_PREPARING) {
            setPrepareState(STATE_PREPARED);
        } else if (mPrepareState == STATE_UNPREPARED) {
            setPrepareState(STATE_UNPREPARED_EOS);
        }
    }

    if (finalStatus == ERROR_END_OF_STREAM) {
        notifyBufferingUpdate(100, 0);
@@ -656,7 +692,30 @@ void NuPlayer::GenericSource::onPollBuffering() {
            percentage = 100;
        }

        ALOGV("Cached duration = %lld(us) %.2f(s)", cachedDurationUs, (float)cachedDurationUs / 1E6);
        if (cachedDurationUs >= kHighWaterMarkUs) {
            mPollBufferDelayUs = 1000000ll;
        } else if (cachedDurationUs <= kLowWaterMarkUs) {
            mPollBufferDelayUs = 100000ll;
        }

        if (mPrepareState == STATE_PREPARING &&
            cachedDurationUs >= kHighWaterMarkUs) {
            setPrepareState(STATE_PREPARED);
        }
        notifyBufferingUpdate(percentage, cachedDurationUs);
    } else {
        ALOGV("Cached data remaining = %dkB", cachedDataRemaining / 1E3);
        if (cachedDataRemaining >= kHighWaterMarkBytes) {
            mPollBufferDelayUs = 1000000ll;
        } else if (cachedDataRemaining <= kLowWaterMarkBytes) {
            mPollBufferDelayUs = 100000ll;
        }

        if (mPrepareState == STATE_PREPARING &&
            cachedDataRemaining >= kHighWaterMarkBytes) {
            setPrepareState(STATE_PREPARED);
        }
    }

    schedulePollBuffering();
+11 −1
Original line number Diff line number Diff line
@@ -75,7 +75,7 @@ struct NuPlayer::GenericSource : public NuPlayer::Source {
    virtual status_t suspend();
    virtual status_t resumeFromSuspended();

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

protected:
    virtual ~GenericSource();
@@ -153,6 +153,15 @@ private:

    bool mStartAfterSuspended;

    enum PrepareState {
        STATE_UNPREPARED = 0,
        STATE_UNPREPARED_EOS,
        STATE_PREPARING,
        STATE_PREPARED
    };
    PrepareState mPrepareState;
    int64_t mPollBufferDelayUs;

    void resetDataSource();

    status_t initFromDataSource();
@@ -201,6 +210,7 @@ private:
    void cancelPollBuffering();
    void onPollBuffering();
    void notifyBufferingUpdate(int percentage, int64_t durationUs);
    void setPrepareState(PrepareState state);

    DISALLOW_EVIL_CONSTRUCTORS(GenericSource);
};