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

Commit 90c2f1e6 authored by Apurupa Pattapu's avatar Apurupa Pattapu Committed by Ricardo Cerqueira
Browse files

frameworks/base/NuPlayer: Handle Seek from NuPlayer

- Seek was handled by the source by queuing discontinuity events
  individually for each stream.With this approach renderer will
  continue till discontinuity events are handled for each stream
- With the new approach seek is handled by the player -
  - get the new seek time from source
  - flush the source TS segments in LiveDataSource, access units
    in TS Parser, decoders and renderer
  - notify current position to driver
  - LiveSession will not queue a discontinuity for seek.
- Add a mutex lock for connect & disconnect ChromiumHTTPDataSource
- Handle flush in ACodec - Idle to Executing & Loaded to Idle states

Conflicts:

	media/libmediaplayerservice/nuplayer/NuPlayer.cpp

Change-Id: I8a741c2c665d3aca715734fc1fd1eeae33a6271b
parent 47e40ae3
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -169,14 +169,21 @@ status_t NuPlayer::HTTPLiveSource::getDuration(int64_t *durationUs) {
    return mLiveSession->getDuration(durationUs);
}

status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) {
status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs, int64_t* newSeekTime) {
    // 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() == OK) {
        usleep(100000);
    }
    if( mFinalResult != OK  ) {
       LOGW("Error state %d, Ignore this seek", mFinalResult);
       return mFinalResult;
    }

    mLiveSession->seekTo(seekTimeUs);
    mLiveSession->seekTo(seekTimeUs, newSeekTime);
    if( *newSeekTime >= 0 ) {
       mTSParser->signalDiscontinuity( ATSParser::DISCONTINUITY_SEEK, NULL);
    }

    return OK;
}
+2 −1
Original line number Diff line number Diff line
@@ -41,7 +41,8 @@ struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
    virtual status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);

    virtual status_t getDuration(int64_t *durationUs);
    virtual status_t seekTo(int64_t seekTimeUs);
    virtual status_t seekTo(int64_t seekTimeUs, int64_t* newSeek = NULL);

    virtual bool isSeekable();

protected:
+69 −3
Original line number Diff line number Diff line
@@ -146,6 +146,7 @@ bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
            return true;

        case FLUSHING_DECODER_SHUTDOWN:
        case SHUTTING_DOWN_DECODER:
            if (needShutdown != NULL) {
                *needShutdown = true;
            }
@@ -294,6 +295,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

                mRenderer->queueEOS(audio, err);
            } else if (what == ACodec::kWhatFlushCompleted) {

                Mutex::Autolock autoLock(mLock);
                bool needShutdown;

                if (audio) {
@@ -369,6 +372,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                }
            } else if (what == ACodec::kWhatShutdownCompleted) {
                LOGV("%s shutdown completed", audio ? "audio" : "video");
                Mutex::Autolock autoLock(mLock);
                if (audio) {
                    mAudioDecoder.clear();

@@ -462,6 +466,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
        case kWhatReset:
        {
            LOGV("kWhatReset");
            Mutex::Autolock autoLock(mLock);

            if (mRenderer != NULL) {
                // There's an edge case where the renderer owns all output
@@ -475,7 +480,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                }
            }

            if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
            if ( (mAudioDecoder != NULL && IsFlushingState(mFlushingAudio)) ||
                 (mVideoDecoder != NULL && IsFlushingState(mFlushingVideo)) ) {
                // We're currently flushing, postpone the reset until that's
                // completed.

@@ -507,18 +513,43 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatSeek:
        {
            int64_t seekTimeUs;
            Mutex::Autolock autoLock(mLock);
            int64_t seekTimeUs = -1, newSeekTime = -1;
            CHECK(msg->findInt64("seekTimeUs", &seekTimeUs));

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

            mSource->seekTo(seekTimeUs);
            mSource->seekTo(seekTimeUs, &newSeekTime);
            LOGV("newSeekTime %lld", newSeekTime);

            if( newSeekTime >= 0 ) {
               if( (mAudioDecoder != NULL) &&
                   (mFlushingAudio == NONE || mFlushingAudio == AWAITING_DISCONTINUITY) ) {
                  flushDecoder( true, true );
               }
               if( (mVideoDecoder != NULL) &&
                   (mFlushingVideo == NONE || mFlushingVideo == AWAITING_DISCONTINUITY) ) {
                  flushDecoder( false, true );
               }
               if( mAudioDecoder == NULL ) {
                   LOGV("Audio is not there, set it to shutdown");
                   mFlushingAudio = SHUT_DOWN;

               }
               if( mVideoDecoder == NULL ) {
                   LOGV("Video is not there, set it to shutdown");
                   mFlushingVideo = SHUT_DOWN;
               }
            }

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

@@ -546,11 +577,27 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
}

void NuPlayer::finishFlushIfPossible() {
    //If reset was postponed after one of the streams is flushed, complete it now
    if (mResetPostponed) {
        LOGV("finishFlushIfPossible Handle reset postpone ");
        if ((mAudioDecoder != NULL) &&
            (mFlushingAudio == NONE || mFlushingAudio == AWAITING_DISCONTINUITY )) {
           flushDecoder( true, true );
        }
        if ((mVideoDecoder != NULL) &&
            (mFlushingVideo == NONE || mFlushingVideo == AWAITING_DISCONTINUITY )) {
           flushDecoder( false, true );
        }
    }

    //Check if both audio & video are flushed
    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
        LOGV("Dont finish flush, audio is in state %d ", mFlushingAudio);
        return;
    }

    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
        LOGV("Dont finish flush, video is in state %d ", mFlushingVideo);
        return;
    }

@@ -562,10 +609,12 @@ void NuPlayer::finishFlushIfPossible() {
    }

    if (mAudioDecoder != NULL) {
        LOGV("Resume Audio after flush");
        mAudioDecoder->signalResume();
    }

    if (mVideoDecoder != NULL) {
        LOGV("Resume Video after flush");
        mVideoDecoder->signalResume();
    }

@@ -580,7 +629,9 @@ void NuPlayer::finishFlushIfPossible() {
    } else if (mResetPostponed) {
        (new AMessage(kWhatReset, id()))->post();
        mResetPostponed = false;
        LOGE("Handle reset postpone");
    } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
        LOGV("Start scanning for sources after shutdown");
        postScanSources();
    }
}
@@ -647,6 +698,17 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
                       new Decoder(notify, mNativeWindow);
    looper()->registerHandler(*decoder);

    {
        //Set flushing state to none
        Mutex::Autolock autoLock(mLock);
        if( audio ) {
            mFlushingAudio = NONE;
        } else {
            mFlushingVideo = NONE;

        }
    }

    (*decoder)->configure(meta);

    int64_t durationUs;
@@ -664,6 +726,8 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
    sp<AMessage> reply;
    CHECK(msg->findMessage("reply", &reply));

    Mutex::Autolock autoLock(mLock);

    if ((audio && IsFlushingState(mFlushingAudio))
            || (!audio && IsFlushingState(mFlushingVideo))) {
        reply->setInt32("err", INFO_DISCONTINUITY);
@@ -783,6 +847,7 @@ void NuPlayer::renderBuffer(bool audio, const sp<AMessage> &msg) {
    sp<AMessage> reply;
    CHECK(msg->findMessage("reply", &reply));

    Mutex::Autolock autoLock(mLock);
    if (IsFlushingState(audio ? mFlushingAudio : mFlushingVideo)) {
        // We're currently attempting to flush the decoder, in order
        // to complete this, the decoder wants all its buffers back,
@@ -878,6 +943,7 @@ void NuPlayer::flushDecoder(bool audio, bool needShutdown) {
                : FLUSHED;
        }
    }
    LOGV("flushDecoder end states Audio %d, Video %d", mFlushingAudio, mFlushingVideo);
}

}  // namespace android
+2 −0
Original line number Diff line number Diff line
@@ -127,6 +127,8 @@ private:
    int64_t mVideoLateByUs;
    int64_t mNumFramesTotal, mNumFramesDropped;

    Mutex mLock;

    status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);

    status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
+1 −1
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ struct NuPlayer::Source : public RefBase {
        return INVALID_OPERATION;
    }

    virtual status_t seekTo(int64_t seekTimeUs) {
    virtual status_t seekTo(int64_t seekTimeUs, int64_t* newSeekTime = NULL ) {
        return INVALID_OPERATION;
    }

Loading