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

Commit 165c6579 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "HTTP Live content that are tagged as complete are now seekable." into gingerbread

parents dfc07279 54d09724
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ public:
    enum Flags {
        kWantsPrefetching      = 1,
        kStreamedFromLocalHost = 2,
        kIsCachingDataSource   = 4,
    };

    static sp<DataSource> CreateFromURI(
+8 −4
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@
#include "include/SoftwareRenderer.h"
#include "include/NuCachedSource2.h"
#include "include/ThrottledSource.h"
#include "include/MPEG2TSExtractor.h"

#include "ARTPSession.h"
#include "APacketSource.h"
@@ -506,8 +507,8 @@ void AwesomePlayer::onBufferingUpdate() {
                // We don't know the bitrate of the stream, use absolute size
                // limits to maintain the cache.

                const size_t kLowWaterMarkBytes = 400000;
                const size_t kHighWaterMarkBytes = 1000000;
                const size_t kLowWaterMarkBytes = 40000;
                const size_t kHighWaterMarkBytes = 200000;

                if ((mFlags & PLAYING) && !eos
                        && (cachedDataRemaining < kLowWaterMarkBytes)) {
@@ -1343,14 +1344,17 @@ status_t AwesomePlayer::finishSetDataSource_l() {
        String8 uri("http://");
        uri.append(mUri.string() + 11);

        dataSource = new LiveSource(uri.string());
        sp<LiveSource> liveSource = new LiveSource(uri.string());

        mCachedSource = new NuCachedSource2(dataSource);
        mCachedSource = new NuCachedSource2(liveSource);
        dataSource = mCachedSource;

        sp<MediaExtractor> extractor =
            MediaExtractor::Create(dataSource, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);

        static_cast<MPEG2TSExtractor *>(extractor.get())
            ->setLiveSource(liveSource);

        return setDataSource_l(extractor);
    } else if (!strncmp("rtsp://gtalk/", mUri.string(), 13)) {
        if (mLooper == NULL) {
+45 −3
Original line number Diff line number Diff line
@@ -179,7 +179,8 @@ NuCachedSource2::NuCachedSource2(const sp<DataSource> &source)
      mFinalStatus(OK),
      mLastAccessPos(0),
      mFetching(true),
      mLastFetchTimeUs(-1) {
      mLastFetchTimeUs(-1),
      mSuspended(false) {
    mLooper->setName("NuCachedSource2");
    mLooper->registerHandler(mReflector);
    mLooper->start();
@@ -205,7 +206,7 @@ status_t NuCachedSource2::getSize(off_t *size) {
}

uint32_t NuCachedSource2::flags() {
    return mSource->flags();
    return (mSource->flags() & ~kWantsPrefetching) | kIsCachingDataSource;
}

void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
@@ -222,6 +223,12 @@ void NuCachedSource2::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatSuspend:
        {
            onSuspend();
            break;
        }

        default:
            TRESPASS();
    }
@@ -263,6 +270,7 @@ void NuCachedSource2::onFetch() {

    bool keepAlive =
        !mFetching
            && !mSuspended
            && mFinalStatus == OK
            && ALooper::GetNowUs() >= mLastFetchTimeUs + kKeepAliveIntervalUs;

@@ -279,7 +287,7 @@ void NuCachedSource2::onFetch() {
            LOGI("Cache full, done prefetching for now");
            mFetching = false;
        }
    } else {
    } else if (!mSuspended) {
        Mutex::Autolock autoLock(mLock);
        restartPrefetcherIfNecessary_l();
    }
@@ -468,5 +476,39 @@ status_t NuCachedSource2::seekInternal_l(off_t offset) {
    return OK;
}

void NuCachedSource2::clearCacheAndResume() {
    LOGV("clearCacheAndResume");

    Mutex::Autolock autoLock(mLock);

    CHECK(mSuspended);

    mCacheOffset = 0;
    mFinalStatus = OK;
    mLastAccessPos = 0;
    mLastFetchTimeUs = -1;

    size_t totalSize = mCache->totalSize();
    CHECK_EQ(mCache->releaseFromStart(totalSize), totalSize);

    mFetching = true;
    mSuspended = false;
}

void NuCachedSource2::suspend() {
    (new AMessage(kWhatSuspend, mReflector->id()))->post();

    while (!mSuspended) {
        usleep(10000);
    }
}

void NuCachedSource2::onSuspend() {
    Mutex::Autolock autoLock(mLock);

    mFetching = false;
    mSuspended = true;
}

}  // namespace android
+69 −1
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ namespace android {
LiveSource::LiveSource(const char *url)
    : mMasterURL(url),
      mInitCheck(NO_INIT),
      mDurationUs(-1),
      mPlaylistIndex(0),
      mLastFetchTimeUs(-1),
      mSource(new NuHTTPDataSource),
@@ -40,6 +41,8 @@ LiveSource::LiveSource(const char *url)
      mPrevBandwidthIndex(-1) {
    if (switchToNext()) {
        mInitCheck = OK;

        determineSeekability();
    }
}

@@ -139,7 +142,7 @@ bool LiveSource::loadPlaylist(bool fetchMaster) {
        }
#else
        // Stay on the lowest bandwidth available.
        size_t index = 0;  // Lowest bandwidth stream
        size_t index = mBandwidthItems.size() - 1;  // Highest bandwidth stream
#endif

        mURL = mBandwidthItems.editItemAt(index).mURI;
@@ -336,4 +339,69 @@ status_t LiveSource::fetchM3U(const char *url, sp<ABuffer> *out) {
    return OK;
}

bool LiveSource::seekTo(int64_t seekTimeUs) {
    LOGV("seek to %lld us", seekTimeUs);

    if (!mPlaylist->isComplete()) {
        return false;
    }

    int32_t targetDuration;
    if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) {
        return false;
    }

    int64_t seekTimeSecs = (seekTimeUs + 500000ll) / 1000000ll;

    int64_t index = seekTimeSecs / targetDuration;

    if (index < 0 || index >= mPlaylist->size()) {
        return false;
    }

    size_t newPlaylistIndex = mFirstItemSequenceNumber + index;

    if (newPlaylistIndex == mPlaylistIndex) {
        return false;
    }

    mPlaylistIndex = newPlaylistIndex;

    switchToNext();
    mOffsetBias = 0;

    LOGV("seeking to index %lld", index);

    return true;
}

bool LiveSource::getDuration(int64_t *durationUs) const {
    if (mDurationUs >= 0) {
        *durationUs = mDurationUs;
        return true;
    }

    *durationUs = 0;
    return false;
}

bool LiveSource::isSeekable() const {
    return mDurationUs >= 0;
}

void LiveSource::determineSeekability() {
    mDurationUs = -1;

    if (!mPlaylist->isComplete()) {
        return;
    }

    int32_t targetDuration;
    if (!mPlaylist->meta()->findInt32("target-duration", &targetDuration)) {
        return;
    }

    mDurationUs = targetDuration * 1000000ll * mPlaylist->size();
}

}  // namespace android
+8 −1
Original line number Diff line number Diff line
@@ -27,7 +27,8 @@ M3UParser::M3UParser(
    : mInitCheck(NO_INIT),
      mBaseURI(baseURI),
      mIsExtM3U(false),
      mIsVariantPlaylist(false) {
      mIsVariantPlaylist(false),
      mIsComplete(false) {
    mInitCheck = parse(data, size);
}

@@ -46,6 +47,10 @@ bool M3UParser::isVariantPlaylist() const {
    return mIsVariantPlaylist;
}

bool M3UParser::isComplete() const {
    return mIsComplete;
}

sp<AMessage> M3UParser::meta() {
    return mMeta;
}
@@ -153,6 +158,8 @@ status_t M3UParser::parse(const void *_data, size_t size) {
                    return ERROR_MALFORMED;
                }
                err = parseMetaData(line, &mMeta, "media-sequence");
            } else if (line.startsWith("#EXT-X-ENDLIST")) {
                mIsComplete = true;
            } else if (line.startsWith("#EXTINF")) {
                if (mIsVariantPlaylist) {
                    return ERROR_MALFORMED;
Loading