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

Commit 0df36ec3 authored by Andreas Huber's avatar Andreas Huber
Browse files

HLS now properly publishes its "seekable" flags after connection

has successfully completed and a sufficient amount of data fetched,
and only then signals that preparation is completed.

Change-Id: I7684a14238b826909f518f2af506966e522dfcfc
parent ec0c597c
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <binder/ProcessState.h>
#include <media/IMediaPlayerService.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
#include "include/LiveSession.h"
#include "include/NuCachedSource2.h"
#include <media/stagefright/AudioPlayer.h>
@@ -1004,7 +1005,7 @@ int main(int argc, char **argv) {
                    looper = new ALooper;
                    looper->start();
                }
                liveSession = new LiveSession;
                liveSession = new LiveSession(NULL /* notify */);
                looper->registerHandler(liveSession);

                liveSession->connect(uri.string());
+57 −17
Original line number Diff line number Diff line
@@ -71,7 +71,10 @@ void NuPlayer::HTTPLiveSource::prepareAsync() {
    mLiveLooper->setName("http live");
    mLiveLooper->start();

    sp<AMessage> notify = new AMessage(kWhatSessionNotify, id());

    mLiveSession = new LiveSession(
            notify,
            (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0,
            mUIDValid, mUID);

@@ -81,23 +84,6 @@ void NuPlayer::HTTPLiveSource::prepareAsync() {
            mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders);

    mTSParser = new ATSParser;

    notifyVideoSizeChanged(0, 0);

    uint32_t flags = FLAG_CAN_PAUSE;
    if (mLiveSession->isSeekable()) {
        flags |= FLAG_CAN_SEEK;
        flags |= FLAG_CAN_SEEK_BACKWARD;
        flags |= FLAG_CAN_SEEK_FORWARD;
    }

    if (mLiveSession->hasDynamicDuration()) {
        flags |= FLAG_DYNAMIC_DURATION;
    }

    notifyFlagsChanged(flags);

    notifyPrepared();
}

void NuPlayer::HTTPLiveSource::start() {
@@ -214,5 +200,59 @@ status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
    return OK;
}

void NuPlayer::HTTPLiveSource::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSessionNotify:
        {
            onSessionNotify(msg);
            break;
        }

        default:
            Source::onMessageReceived(msg);
            break;
    }
}

void NuPlayer::HTTPLiveSource::onSessionNotify(const sp<AMessage> &msg) {
    int32_t what;
    CHECK(msg->findInt32("what", &what));

    switch (what) {
        case LiveSession::kWhatPrepared:
        {
            notifyVideoSizeChanged(0, 0);

            uint32_t flags = FLAG_CAN_PAUSE;
            if (mLiveSession->isSeekable()) {
                flags |= FLAG_CAN_SEEK;
                flags |= FLAG_CAN_SEEK_BACKWARD;
                flags |= FLAG_CAN_SEEK_FORWARD;
            }

            if (mLiveSession->hasDynamicDuration()) {
                flags |= FLAG_DYNAMIC_DURATION;
            }

            notifyFlagsChanged(flags);

            notifyPrepared();
            break;
        }

        case LiveSession::kWhatPreparationFailed:
        {
            status_t err;
            CHECK(msg->findInt32("err", &err));

            notifyPrepared(err);
            break;
        }

        default:
            TRESPASS();
    }
}

}  // namespace android
+8 −0
Original line number Diff line number Diff line
@@ -49,12 +49,18 @@ protected:

    virtual sp<MetaData> getFormatMeta(bool audio);

    virtual void onMessageReceived(const sp<AMessage> &msg);

private:
    enum Flags {
        // Don't log any URLs.
        kFlagIncognito = 1,
    };

    enum {
        kWhatSessionNotify,
    };

    AString mURL;
    KeyedVector<String8, String8> mExtraHeaders;
    bool mUIDValid;
@@ -66,6 +72,8 @@ private:
    sp<LiveSession> mLiveSession;
    sp<ATSParser> mTSParser;

    void onSessionNotify(const sp<AMessage> &msg);

    DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource);
};

+2 −1
Original line number Diff line number Diff line
@@ -82,7 +82,8 @@ status_t ALooperRoster::postMessage_l(
    ssize_t index = mHandlers.indexOfKey(msg->target());

    if (index < 0) {
        ALOGW("failed to post message. Target handler not registered.");
        ALOGW("failed to post message '%s'. Target handler not registered.",
              msg->debugString().c_str());
        return -ENOENT;
    }

+44 −9
Original line number Diff line number Diff line
@@ -40,10 +40,13 @@

namespace android {

LiveSession::LiveSession(uint32_t flags, bool uidValid, uid_t uid)
    : mFlags(flags),
LiveSession::LiveSession(
        const sp<AMessage> &notify, uint32_t flags, bool uidValid, uid_t uid)
    : mNotify(notify),
      mFlags(flags),
      mUIDValid(uidValid),
      mUID(uid),
      mInPreparationPhase(true),
      mDataSource(new LiveDataSource),
      mHTTPDataSource(
              HTTPBase::Create(
@@ -179,7 +182,7 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
    if (playlist == NULL) {
        ALOGE("unable to fetch master playlist '%s'.", url.c_str());

        mDataSource->queueEOS(ERROR_IO);
        signalEOS(ERROR_IO);
        return;
    }

@@ -207,7 +210,7 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
void LiveSession::onDisconnect() {
    ALOGI("onDisconnect");

    mDataSource->queueEOS(ERROR_END_OF_STREAM);
    signalEOS(ERROR_END_OF_STREAM);

    Mutex::Autolock autoLock(mLock);
    mDisconnectPending = false;
@@ -561,7 +564,8 @@ rinse_repeat:
                // unchanged from the last time we tried.
            } else {
                ALOGE("failed to load playlist at url '%s'", url.c_str());
                mDataSource->queueEOS(ERROR_IO);
                signalEOS(ERROR_IO);

                return;
            }
        } else {
@@ -704,7 +708,7 @@ rinse_repeat:
                 mSeqNumber, firstSeqNumberInPlaylist,
                 firstSeqNumberInPlaylist + mPlaylist->size() - 1);

            mDataSource->queueEOS(ERROR_END_OF_STREAM);
            signalEOS(ERROR_END_OF_STREAM);
            return;
        }
    }
@@ -737,7 +741,7 @@ rinse_repeat:
    status_t err = fetchFile(uri.c_str(), &buffer, range_offset, range_length);
    if (err != OK) {
        ALOGE("failed to fetch .ts segment at url '%s'", uri.c_str());
        mDataSource->queueEOS(err);
        signalEOS(err);
        return;
    }

@@ -748,7 +752,7 @@ rinse_repeat:
    if (err != OK) {
        ALOGE("decryptBuffer failed w/ error %d", err);

        mDataSource->queueEOS(err);
        signalEOS(err);
        return;
    }

@@ -760,7 +764,7 @@ rinse_repeat:
        mBandwidthItems.removeAt(bandwidthIndex);

        if (mBandwidthItems.isEmpty()) {
            mDataSource->queueEOS(ERROR_UNSUPPORTED);
            signalEOS(ERROR_UNSUPPORTED);
            return;
        }

@@ -824,11 +828,42 @@ rinse_repeat:
    postMonitorQueue();
}

void LiveSession::signalEOS(status_t err) {
    if (mInPreparationPhase && mNotify != NULL) {
        sp<AMessage> notify = mNotify->dup();

        notify->setInt32(
                "what",
                err == ERROR_END_OF_STREAM
                    ? kWhatPrepared : kWhatPreparationFailed);

        if (err != ERROR_END_OF_STREAM) {
            notify->setInt32("err", err);
        }

        notify->post();

        mInPreparationPhase = false;
    }

    mDataSource->queueEOS(err);
}

void LiveSession::onMonitorQueue() {
    if (mSeekTimeUs >= 0
            || mDataSource->countQueuedBuffers() < kMaxNumQueuedFragments) {
        onDownloadNext();
    } else {
        if (mInPreparationPhase) {
            if (mNotify != NULL) {
                sp<AMessage> notify = mNotify->dup();
                notify->setInt32("what", kWhatPrepared);
                notify->post();
            }

            mInPreparationPhase = false;
        }

        postMonitorQueue(1000000ll);
    }
}
Loading