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

Commit f013dc41 authored by Robert Shih's avatar Robert Shih Committed by Android (Google) Code Review
Browse files

Merge "Miscellaneous RTSP improvements" into nyc-dev

parents e736431c 641e0c71
Loading
Loading
Loading
Loading
+78 −24
Original line number Diff line number Diff line
@@ -32,6 +32,12 @@ namespace android {

const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs

// Buffer Underflow/Prepare/StartServer/Overflow Marks
const int64_t NuPlayer::RTSPSource::kUnderflowMarkUs   =  1000000ll;
const int64_t NuPlayer::RTSPSource::kPrepareMarkUs     =  3000000ll;
const int64_t NuPlayer::RTSPSource::kStartServerMarkUs =  5000000ll;
const int64_t NuPlayer::RTSPSource::kOverflowMarkUs    = 10000000ll;

NuPlayer::RTSPSource::RTSPSource(
        const sp<AMessage> &notify,
        const sp<IMediaHTTPService> &httpService,
@@ -51,6 +57,7 @@ NuPlayer::RTSPSource::RTSPSource(
      mFinalResult(OK),
      mDisconnectReplyID(0),
      mBuffering(false),
      mInPreparationPhase(true),
      mSeekGeneration(0),
      mEOSTimeoutAudio(0),
      mEOSTimeoutVideo(0) {
@@ -127,29 +134,6 @@ void NuPlayer::RTSPSource::stop() {
    msg->postAndAwaitResponse(&dummy);
}

void NuPlayer::RTSPSource::pause() {
    int64_t mediaDurationUs = 0;
    getDuration(&mediaDurationUs);
    for (size_t index = 0; index < mTracks.size(); index++) {
        TrackInfo *info = &mTracks.editItemAt(index);
        sp<AnotherPacketSource> source = info->mSource;

        // Check if EOS or ERROR is received
        if (source != NULL && source->isFinished(mediaDurationUs)) {
            return;
        }
    }
    if (mHandler != NULL) {
        mHandler->pause();
    }
}

void NuPlayer::RTSPSource::resume() {
    if (mHandler != NULL) {
        mHandler->resume();
    }
}

status_t NuPlayer::RTSPSource::feedMoreTSData() {
    Mutex::Autolock _l(mBufferingLock);
    return mFinalResult;
@@ -324,6 +308,73 @@ void NuPlayer::RTSPSource::performSeek(int64_t seekTimeUs) {
    mHandler->seek(seekTimeUs);
}

void NuPlayer::RTSPSource::schedulePollBuffering() {
    sp<AMessage> msg = new AMessage(kWhatPollBuffering, this);
    msg->post(1000000ll); // 1 second intervals
}

void NuPlayer::RTSPSource::checkBuffering(
        bool *prepared, bool *underflow, bool *overflow, bool *startServer) {
    size_t numTracks = mTracks.size();
    size_t preparedCount, underflowCount, overflowCount, startCount;
    preparedCount = underflowCount = overflowCount = startCount = 0;
    for (size_t i = 0; i < numTracks; ++i) {
        status_t finalResult;
        TrackInfo *info = &mTracks.editItemAt(i);
        sp<AnotherPacketSource> src = info->mSource;
        int64_t bufferedDurationUs = src->getBufferedDurationUs(&finalResult);

        // isFinished when duration is 0 checks for EOS result only
        if (bufferedDurationUs > kPrepareMarkUs || src->isFinished(/* duration */ 0)) {
            ++preparedCount;
        }

        if (src->isFinished(/* duration */ 0)) {
            ++overflowCount;
        } else {
            if (bufferedDurationUs < kUnderflowMarkUs) {
                ++underflowCount;
            }
            if (bufferedDurationUs > kOverflowMarkUs) {
                ++overflowCount;
            }
            if (bufferedDurationUs < kStartServerMarkUs) {
                ++startCount;
            }
        }
    }

    *prepared    = (preparedCount == numTracks);
    *underflow   = (underflowCount > 0);
    *overflow    = (overflowCount == numTracks);
    *startServer = (startCount > 0);
}

void NuPlayer::RTSPSource::onPollBuffering() {
    bool prepared, underflow, overflow, startServer;
    checkBuffering(&prepared, &underflow, &overflow, &startServer);

    if (prepared && mInPreparationPhase) {
        mInPreparationPhase = false;
        notifyPrepared();
    }

    if (!mInPreparationPhase && underflow) {
        startBufferingIfNecessary();
    }

    if (overflow && mHandler != NULL) {
        stopBufferingIfNecessary();
        mHandler->pause();
    }

    if (startServer && mHandler != NULL) {
        mHandler->resume();
    }

    schedulePollBuffering();
}

void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
    if (msg->what() == kWhatDisconnect) {
        sp<AReplyToken> replyID;
@@ -348,6 +399,9 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {

        performSeek(seekTimeUs);
        return;
    } else if (msg->what() == kWhatPollBuffering) {
        onPollBuffering();
        return;
    }

    CHECK_EQ(msg->what(), (int)kWhatNotify);
@@ -372,7 +426,7 @@ void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
            }

            notifyFlagsChanged(flags);
            notifyPrepared();
            schedulePollBuffering();
            break;
        }

+11 −2
Original line number Diff line number Diff line
@@ -43,8 +43,6 @@ struct NuPlayer::RTSPSource : public NuPlayer::Source {
    virtual void prepareAsync();
    virtual void start();
    virtual void stop();
    virtual void pause();
    virtual void resume();

    virtual status_t feedMoreTSData();

@@ -65,6 +63,7 @@ private:
        kWhatNotify          = 'noti',
        kWhatDisconnect      = 'disc',
        kWhatPerformSeek     = 'seek',
        kWhatPollBuffering   = 'poll',
    };

    enum State {
@@ -79,6 +78,12 @@ private:
        kFlagIncognito = 1,
    };

    // Buffer Prepare/Underflow/Overflow/Resume Marks
    static const int64_t kPrepareMarkUs;
    static const int64_t kUnderflowMarkUs;
    static const int64_t kOverflowMarkUs;
    static const int64_t kStartServerMarkUs;

    struct TrackInfo {
        sp<AnotherPacketSource> mSource;

@@ -100,6 +105,7 @@ private:
    sp<AReplyToken> mDisconnectReplyID;
    Mutex mBufferingLock;
    bool mBuffering;
    bool mInPreparationPhase;

    sp<ALooper> mLooper;
    sp<MyHandler> mHandler;
@@ -126,6 +132,9 @@ private:
    void finishDisconnectIfPossible();

    void performSeek(int64_t seekTimeUs);
    void schedulePollBuffering();
    void checkBuffering(bool *prepared, bool *underflow, bool *overflow, bool *startServer);
    void onPollBuffering();

    bool haveSufficientDataOnAllTracks();

+12 −1
Original line number Diff line number Diff line
@@ -235,7 +235,7 @@ struct MyHandler : public AHandler {
        sp<AMessage> msg = new AMessage('paus', this);
        mPauseGeneration++;
        msg->setInt32("pausecheck", mPauseGeneration);
        msg->post(kPauseDelayUs);
        msg->post();
    }

    void resume() {
@@ -979,6 +979,11 @@ struct MyHandler : public AHandler {

            case 'accu':
            {
                if (mSeekPending) {
                    ALOGV("Stale access unit.");
                    break;
                }

                int32_t timeUpdate;
                if (msg->findInt32("time-update", &timeUpdate) && timeUpdate) {
                    size_t trackIndex;
@@ -1070,6 +1075,12 @@ struct MyHandler : public AHandler {
                    ALOGW("This is a live stream, ignoring pause request.");
                    break;
                }

                if (mPausing) {
                    ALOGV("This stream is already paused.");
                    break;
                }

                mCheckPending = true;
                ++mCheckGeneration;
                mPausing = true;