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

Commit 5b1b8a93 authored by James Dong's avatar James Dong
Browse files

Send estimated bandwidth value as informational event when cache fetcher pauses

o Application can make informed decision about the available network bandwidth
  when cache fetcher pauses.

o Application can also adjust how frequently the bandwidth is estimated within
  a range from one second to one minute.

Change-Id: I90068001343e79da1886de03c565537787e1580b
parent 65580f9a
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -100,6 +100,9 @@ enum media_info_type {
    MEDIA_INFO_BUFFERING_START = 701,
    // MediaPlayer is resuming playback after filling buffers.
    MEDIA_INFO_BUFFERING_END = 702,
    // Bandwidth in recent past
    MEDIA_INFO_NETWORK_BANDWIDTH = 703,

    // 8xx
    // Bad interleaving means that a media has been improperly interleaved or not
    // interleaved at all, e.g has all the video samples first then all the audio
@@ -128,6 +131,9 @@ enum media_player_states {
enum media_set_parameter_keys {
    KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX = 1000,
    KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE = 1001,

    // Streaming/buffering parameters
    KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS = 1100,
};
// ----------------------------------------------------------------------------
// ref-counted object for callbacks
+28 −0
Original line number Diff line number Diff line
@@ -634,6 +634,7 @@ void AwesomePlayer::onBufferingUpdate() {
                    mFlags |= CACHE_UNDERRUN;
                    pause_l();
                    ensureCacheIsFetching_l();
                    sendCacheStats();
                    notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
                } else if (eos || cachedDataRemaining > kHighWaterMarkBytes) {
                    if (mFlags & CACHE_UNDERRUN) {
@@ -692,6 +693,7 @@ void AwesomePlayer::onBufferingUpdate() {
            mFlags |= CACHE_UNDERRUN;
            pause_l();
            ensureCacheIsFetching_l();
            sendCacheStats();
            notifyListener_l(MEDIA_INFO, MEDIA_INFO_BUFFERING_START);
        } else if (eos || cachedDurationUs > highWaterMarkUs) {
            if (mFlags & CACHE_UNDERRUN) {
@@ -711,6 +713,18 @@ void AwesomePlayer::onBufferingUpdate() {
    postBufferingEvent_l();
}

void AwesomePlayer::sendCacheStats() {
    sp<MediaPlayerBase> listener = mListener.promote();
    if (listener != NULL) {
        int32_t kbps = 0;
        status_t err = mCachedSource->getEstimatedBandwidthKbps(&kbps);
        if (err == OK) {
            listener->sendEvent(
                MEDIA_INFO, MEDIA_INFO_NETWORK_BANDWIDTH, kbps);
        }
    }
}

void AwesomePlayer::onStreamDone() {
    // Posted whenever any stream finishes playing.

@@ -2083,6 +2097,10 @@ status_t AwesomePlayer::setParameter(int key, const Parcel &request) {

            return mTextPlayer->setParameter(key, request);
        }
        case KEY_PARAMETER_CACHE_STAT_COLLECT_FREQ_MS:
        {
            return setCacheStatCollectFreq(request);
        }
        default:
        {
            return ERROR_UNSUPPORTED;
@@ -2090,6 +2108,16 @@ status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
    }
}

status_t AwesomePlayer::setCacheStatCollectFreq(const Parcel &request) {
    if (mCachedSource != NULL) {
        int32_t freqMs = request.readInt32();
        LOGD("Request to keep cache stats in the past %d ms",
            freqMs);
        return mCachedSource->setCacheStatCollectFreq(freqMs);
    }
    return ERROR_UNSUPPORTED;
}

status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
    return OK;
}
+78 −1
Original line number Diff line number Diff line
@@ -14,6 +14,10 @@
 * limitations under the License.
 */

//#define LOG_NDEBUG 0
#define LOG_TAG "HTTPBase"
#include <utils/Log.h>

#include "include/HTTPBase.h"

#if CHROMIUM_AVAILABLE
@@ -22,11 +26,19 @@

#include "include/NuHTTPDataSource.h"

#include <media/stagefright/foundation/ALooper.h>
#include <cutils/properties.h>

namespace android {

HTTPBase::HTTPBase() {}
HTTPBase::HTTPBase()
    : mNumBandwidthHistoryItems(0),
      mTotalTransferTimeUs(0),
      mTotalTransferBytes(0),
      mPrevBandwidthMeasureTimeUs(0),
      mPrevEstimatedBandWidthKbps(0),
      mBandWidthCollectFreqMs(5000) {
}

// static
sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
@@ -42,4 +54,69 @@ sp<HTTPBase> HTTPBase::Create(uint32_t flags) {
    }
}

void HTTPBase::addBandwidthMeasurement(
        size_t numBytes, int64_t delayUs) {
    Mutex::Autolock autoLock(mLock);

    BandwidthEntry entry;
    entry.mDelayUs = delayUs;
    entry.mNumBytes = numBytes;
    mTotalTransferTimeUs += delayUs;
    mTotalTransferBytes += numBytes;

    mBandwidthHistory.push_back(entry);
    if (++mNumBandwidthHistoryItems > 100) {
        BandwidthEntry *entry = &*mBandwidthHistory.begin();
        mTotalTransferTimeUs -= entry->mDelayUs;
        mTotalTransferBytes -= entry->mNumBytes;
        mBandwidthHistory.erase(mBandwidthHistory.begin());
        --mNumBandwidthHistoryItems;

        int64_t timeNowUs = ALooper::GetNowUs();
        if (timeNowUs - mPrevBandwidthMeasureTimeUs >=
                mBandWidthCollectFreqMs * 1000LL) {

            if (mPrevBandwidthMeasureTimeUs != 0) {
                mPrevEstimatedBandWidthKbps =
                    (mTotalTransferBytes * 8E3 / mTotalTransferTimeUs);
            }
            mPrevBandwidthMeasureTimeUs = timeNowUs;
        }
    }

}

bool HTTPBase::estimateBandwidth(int32_t *bandwidth_bps) {
    Mutex::Autolock autoLock(mLock);

    if (mNumBandwidthHistoryItems < 2) {
        return false;
    }

    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);

    return true;
}

status_t HTTPBase::getEstimatedBandwidthKbps(int32_t *kbps) {
    Mutex::Autolock autoLock(mLock);
    *kbps = mPrevEstimatedBandWidthKbps;
    return OK;
}

status_t HTTPBase::setBandwidthStatCollectFreq(int32_t freqMs) {
    Mutex::Autolock autoLock(mLock);

    if (freqMs < kMinBandwidthCollectFreqMs
            || freqMs > kMaxBandwidthCollectFreqMs) {

        LOGE("frequency (%d ms) is out of range [1000, 60000]", freqMs);
        return BAD_VALUE;
    }

    LOGI("frequency set to %d ms", freqMs);
    mBandWidthCollectFreqMs = freqMs;
    return OK;
}

}  // namespace android
+11 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include <utils/Log.h>

#include "include/NuCachedSource2.h"
#include "include/HTTPBase.h"

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
@@ -201,6 +202,16 @@ NuCachedSource2::~NuCachedSource2() {
    mCache = NULL;
}

status_t NuCachedSource2::getEstimatedBandwidthKbps(int32_t *kbps) {
    HTTPBase* source = static_cast<HTTPBase *>(mSource.get());
    return source->getEstimatedBandwidthKbps(kbps);
}

status_t NuCachedSource2::setCacheStatCollectFreq(int32_t freqMs) {
    HTTPBase *source = static_cast<HTTPBase *>(mSource.get());
    return source->setBandwidthStatCollectFreq(freqMs);
}

status_t NuCachedSource2::initCheck() const {
    return mSource->initCheck();
}
+1 −34
Original line number Diff line number Diff line
@@ -97,9 +97,6 @@ NuHTTPDataSource::NuHTTPDataSource(uint32_t flags)
      mContentLengthValid(false),
      mHasChunkedTransferEncoding(false),
      mChunkDataBytesLeft(0),
      mNumBandwidthHistoryItems(0),
      mTotalTransferTimeUs(0),
      mTotalTransferBytes(0),
      mDecryptHandle(NULL),
      mDrmManagerClient(NULL) {
}
@@ -431,7 +428,7 @@ ssize_t NuHTTPDataSource::readAt(off64_t offset, void *data, size_t size) {
        }

        int64_t delayUs = ALooper::GetNowUs() - startTimeUs;
        addBandwidthMeasurement_l(n, delayUs);
        addBandwidthMeasurement(n, delayUs);

        numBytesRead += (size_t)n;

@@ -517,36 +514,6 @@ void NuHTTPDataSource::applyTimeoutResponse() {
    }
}

bool NuHTTPDataSource::estimateBandwidth(int32_t *bandwidth_bps) {
    Mutex::Autolock autoLock(mLock);

    if (mNumBandwidthHistoryItems < 2) {
        return false;
    }

    *bandwidth_bps = ((double)mTotalTransferBytes * 8E6 / mTotalTransferTimeUs);

    return true;
}

void NuHTTPDataSource::addBandwidthMeasurement_l(
        size_t numBytes, int64_t delayUs) {
    BandwidthEntry entry;
    entry.mDelayUs = delayUs;
    entry.mNumBytes = numBytes;
    mTotalTransferTimeUs += delayUs;
    mTotalTransferBytes += numBytes;

    mBandwidthHistory.push_back(entry);
    if (++mNumBandwidthHistoryItems > 100) {
        BandwidthEntry *entry = &*mBandwidthHistory.begin();
        mTotalTransferTimeUs -= entry->mDelayUs;
        mTotalTransferBytes -= entry->mNumBytes;
        mBandwidthHistory.erase(mBandwidthHistory.begin());
        --mNumBandwidthHistoryItems;
    }
}

sp<DecryptHandle> NuHTTPDataSource::DrmInitialization() {
    if (mDrmManagerClient == NULL) {
        mDrmManagerClient = new DrmManagerClient();
Loading