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

Commit 43c3e6ce authored by Andreas Huber's avatar Andreas Huber
Browse files

Seek/Duration support for completed http live streams in NuPlayer.

Change-Id: I55bbe75d87140c07b1927d14ad24130fce803463
related-to-bug: 3321475
parent 627baacc
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ enum media_event_type {
    MEDIA_BUFFERING_UPDATE  = 3,
    MEDIA_SEEK_COMPLETE     = 4,
    MEDIA_SET_VIDEO_SIZE    = 5,
    MEDIA_RESET_COMPLETE    = 6,  // not visible on java side
    MEDIA_ERROR             = 100,
    MEDIA_INFO              = 200,
};
+20 −0
Original line number Diff line number Diff line
@@ -128,5 +128,25 @@ status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
    return source->dequeueAccessUnit(accessUnit);
}

status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
    return mLiveSession->getDuration(durationUs);
}

status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
    // We need to make sure we're not seeking until we have seen the very first
    // PTS timestamp in the whole stream (from the beginning of the stream).
    while (!mTSParser->PTSTimeDeltaEstablished() && feedMoreTSData()) {
        usleep(100000);
    }

    mLiveSession->seekTo(seekTimeUs);

    return OK;
}

bool NuPlayer::HTTPLiveSource::isSeekable() {
    return mLiveSession->isSeekable();
}

}  // namespace android
+8 −4
Original line number Diff line number Diff line
@@ -29,13 +29,17 @@ struct LiveSession;
struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
    HTTPLiveSource(const char *url);

    void start();
    virtual void start();

    // Returns true iff more data was available, false on EOS.
    bool feedMoreTSData();
    virtual bool feedMoreTSData();

    sp<MetaData> getFormat(bool audio);
    status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
    virtual sp<MetaData> getFormat(bool audio);
    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);

    virtual status_t getDuration(int64_t *durationUs);
    virtual status_t seekTo(int64_t seekTimeUs);
    virtual bool isSeekable();

protected:
    virtual ~HTTPLiveSource();
+73 −9
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@

#include "HTTPLiveSource.h"
#include "NuPlayerDecoder.h"
#include "NuPlayerDriver.h"
#include "NuPlayerRenderer.h"
#include "NuPlayerSource.h"
#include "StreamingSource.h"
@@ -55,8 +56,8 @@ NuPlayer::NuPlayer()
NuPlayer::~NuPlayer() {
}

void NuPlayer::setListener(const wp<MediaPlayerBase> &listener) {
    mListener = listener;
void NuPlayer::setDriver(const wp<NuPlayerDriver> &driver) {
    mDriver = driver;
}

void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
@@ -90,10 +91,24 @@ void NuPlayer::start() {
    (new AMessage(kWhatStart, id()))->post();
}

void NuPlayer::pause() {
    // XXX to be implemented
}

void NuPlayer::resume() {
    // XXX to be implemented
}

void NuPlayer::resetAsync() {
    (new AMessage(kWhatReset, id()))->post();
}

void NuPlayer::seekToAsync(int64_t seekTimeUs) {
    sp<AMessage> msg = new AMessage(kWhatSeek, id());
    msg->setInt64("seekTimeUs", seekTimeUs);
    msg->post();
}

// static
bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
    switch (state) {
@@ -153,6 +168,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatStart:
        {
            LOGV("kWhatStart");

            mAudioEOS = false;
            mVideoEOS = false;

@@ -179,6 +196,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

            mScanSourcesPending = false;

            LOGV("scanning sources haveAudio=%d, haveVideo=%d",
                 mAudioDecoder != NULL, mVideoDecoder != NULL);

            instantiateDecoder(false, &mVideoDecoder);

            if (mAudioSink != NULL) {
@@ -312,6 +332,16 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                        && (mVideoEOS || mVideoDecoder == NULL)) {
                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
                }
            } else if (what == Renderer::kWhatPosition) {
                int64_t positionUs;
                CHECK(msg->findInt64("positionUs", &positionUs));

                if (mDriver != NULL) {
                    sp<NuPlayerDriver> driver = mDriver.promote();
                    if (driver != NULL) {
                        driver->notifyPosition(positionUs);
                    }
                }
            } else {
                CHECK_EQ(what, (int32_t)Renderer::kWhatFlushComplete);

@@ -359,6 +389,26 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatSeek:
        {
            int64_t seekTimeUs;
            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));

            LOGI("kWhatSeek seekTimeUs=%lld us (%.2f secs)",
                 seekTimeUs, seekTimeUs / 1E6);

            mSource->seekTo(seekTimeUs);

            if (mDriver != NULL) {
                sp<NuPlayerDriver> driver = mDriver.promote();
                if (driver != NULL) {
                    driver->notifySeekComplete();
                }
            }

            break;
        }

        default:
            TRESPASS();
            break;
@@ -415,7 +465,12 @@ void NuPlayer::finishReset() {
    mRenderer.clear();
    mSource.clear();

    notifyListener(MEDIA_RESET_COMPLETE, 0, 0);
    if (mDriver != NULL) {
        sp<NuPlayerDriver> driver = mDriver.promote();
        if (driver != NULL) {
            driver->notifyResetComplete();
        }
    }
}

void NuPlayer::postScanSources() {
@@ -450,6 +505,14 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {

    (*decoder)->configure(meta);

    int64_t durationUs;
    if (mDriver != NULL && mSource->getDuration(&durationUs) == OK) {
        sp<NuPlayerDriver> driver = mDriver.promote();
        if (driver != NULL) {
            driver->notifyDuration(durationUs);
        }
    }

    return OK;
}

@@ -488,7 +551,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
        return OK;
    }

    LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");
    // LOGV("returned a valid buffer of %s data", audio ? "audio" : "video");

#if 0
    int64_t mediaTimeUs;
@@ -505,7 +568,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
}

void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
    LOGV("renderBuffer %s", audio ? "audio" : "video");
    // LOGV("renderBuffer %s", audio ? "audio" : "video");

    sp<AMessage> reply;
    CHECK(msg->findMessage("reply", &reply));
@@ -519,22 +582,23 @@ void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
}

void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
    if (mListener == NULL) {
    if (mDriver == NULL) {
        return;
    }

    sp<MediaPlayerBase> listener = mListener.promote();
    sp<NuPlayerDriver> driver = mDriver.promote();

    if (listener == NULL) {
    if (driver == NULL) {
        return;
    }

    listener->sendEvent(msg, ext1, ext2);
    driver->sendEvent(msg, ext1, ext2);
}

void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
    // Make sure we don't continue to scan sources until we finish flushing.
    ++mScanSourcesGeneration;
    mScanSourcesPending = false;

    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
    mRenderer->flush(audio);
+11 −4
Original line number Diff line number Diff line
@@ -25,11 +25,12 @@ namespace android {

struct ACodec;
struct MetaData;
struct NuPlayerDriver;

struct NuPlayer : public AHandler {
    NuPlayer();

    void setListener(const wp<MediaPlayerBase> &listener);
    void setDriver(const wp<NuPlayerDriver> &driver);

    void setDataSource(const sp<IStreamSource> &source);

@@ -40,10 +41,15 @@ struct NuPlayer : public AHandler {
    void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
    void start();

    // Will notify the listener that reset() has completed
    // with code MEDIA_RESET_COMPLETE.
    void pause();
    void resume();

    // Will notify the driver through "notifyResetComplete" once finished.
    void resetAsync();

    // Will notify the driver through "notifySeekComplete" once finished.
    void seekToAsync(int64_t seekTimeUs);

protected:
    virtual ~NuPlayer();

@@ -68,9 +74,10 @@ private:
        kWhatAudioNotify,
        kWhatRendererNotify,
        kWhatReset,
        kWhatSeek,
    };

    wp<MediaPlayerBase> mListener;
    wp<NuPlayerDriver> mDriver;
    sp<Source> mSource;
    sp<Surface> mSurface;
    sp<MediaPlayerBase::AudioSink> mAudioSink;
Loading