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

Commit d1864f9a authored by Wei Jia's avatar Wei Jia
Browse files

NuPlayer2: support end position of data source

Test: cts
Bug: 112549021
Change-Id: I5143754eb22fa42c3134474c584d986eb6f2b33d
parent 0a0c0278
Loading
Loading
Loading
Loading
+130 −32
Original line number Diff line number Diff line
@@ -216,6 +216,7 @@ NuPlayer2::NuPlayer2(pid_t pid, uid_t uid, const sp<MediaClock> &mediaClock)
      mAudioDecoderGeneration(0),
      mVideoDecoderGeneration(0),
      mRendererGeneration(0),
      mEOSMonitorGeneration(0),
      mLastStartedPlayingTimeNs(0),
      mPreviousSeekTimeUs(0),
      mAudioEOS(false),
@@ -586,6 +587,11 @@ void NuPlayer2::seekToAsync(int64_t seekTimeUs, MediaPlayer2SeekMode mode, bool
    msg->post();
}

void NuPlayer2::rewind() {
    sp<AMessage> msg = new AMessage(kWhatRewind, this);
    msg->post();
}

void NuPlayer2::writeTrackInfo(
        PlayerMessage* reply, const sp<AMessage>& format) const {
    if (format == NULL) {
@@ -713,6 +719,22 @@ void NuPlayer2::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatEOSMonitor:
        {
            int32_t generation;
            CHECK(msg->findInt32("generation", &generation));
            int32_t reason;
            CHECK(msg->findInt32("reason", &reason));

            if (generation != mEOSMonitorGeneration || reason != MediaClock::TIMER_REASON_REACHED) {
                break;  // stale or reset
            }

            ALOGV("kWhatEOSMonitor");
            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PLAYBACK_COMPLETE, 0, 0);
            break;
        }

        case kWhatGetBufferingSettings:
        {
            sp<AReplyToken> replyID;
@@ -1522,6 +1544,42 @@ void NuPlayer2::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatRewind:
        {
            ALOGV("kWhatRewind");

            int64_t seekTimeUs = mCurrentSourceInfo.mStartTimeUs;
            int32_t mode = MediaPlayer2SeekMode::SEEK_CLOSEST;

            if (!mStarted) {
                if (!mSourceStarted) {
                    mSourceStarted = true;
                    mCurrentSourceInfo.mSource->start();
                }
                performSeek(seekTimeUs, (MediaPlayer2SeekMode)mode);
                break;
            }

            // seeks can take a while, so we essentially paused
            notifyListener(mCurrentSourceInfo.mSrcId, MEDIA2_PAUSED, 0, 0);

            mDeferredActions.push_back(
                    new FlushDecoderAction(FLUSH_CMD_FLUSH /* audio */,
                                           FLUSH_CMD_FLUSH /* video */));

            mDeferredActions.push_back(
                    new SeekAction(seekTimeUs, (MediaPlayer2SeekMode)mode));

            // After a flush without shutdown, decoder is paused.
            // Don't resume it until source seek is done, otherwise it could
            // start pulling stale data too soon.
            mDeferredActions.push_back(
                    new ResumeDecoderAction(false /* needNotify */));

            processDeferredActions();
            break;
        }

        case kWhatPause:
        {
            if (!mStarted) {
@@ -1675,6 +1733,7 @@ void NuPlayer2::onStart(bool play) {
        mRenderer->setVideoFrameRate(rate);
    }

    addEndTimeMonitor();
    // Renderer is created in paused state.
    if (play) {
        mRenderer->resume();
@@ -1693,6 +1752,13 @@ void NuPlayer2::onStart(bool play) {
    postScanSources();
}

void NuPlayer2::addEndTimeMonitor() {
    sp<AMessage> msg = new AMessage(kWhatEOSMonitor, this);
    ++mEOSMonitorGeneration;
    msg->setInt32("generation", mEOSMonitorGeneration);
    mMediaClock->addTimer(msg, mCurrentSourceInfo.mEndTimeUs);
}

void NuPlayer2::startPlaybackTimer(const char *where) {
    Mutex::Autolock autoLock(mPlayingTimeLock);
    if (mLastStartedPlayingTimeNs == 0) {
@@ -2473,17 +2539,22 @@ void NuPlayer2::performPlayNextDataSource() {
    long previousSrcId;
    {
        Mutex::Autolock autoLock(mSourceLock);
        mCurrentSourceInfo.mSource = mNextSourceInfo.mSource;
        mNextSourceInfo.mSource = NULL;
        previousSrcId = mCurrentSourceInfo.mSrcId;
        mCurrentSourceInfo.mSrcId = mNextSourceInfo.mSrcId;
        ++mNextSourceInfo.mSrcId;  // to distinguish the two sources.

        mCurrentSourceInfo = mNextSourceInfo;
        mNextSourceInfo = SourceInfo();
        mNextSourceInfo.mSrcId = ~mCurrentSourceInfo.mSrcId;  // to distinguish the two sources.
    }

    if (mDriver != NULL) {
        sp<NuPlayer2Driver> driver = mDriver.promote();
        if (driver != NULL) {
            notifyListener(previousSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_END, 0);

            int64_t durationUs;
            if (mCurrentSourceInfo.mSource->getDuration(&durationUs) == OK) {
                driver->notifyDuration(mCurrentSourceInfo.mSrcId, durationUs);
            }
            notifyListener(
                    mCurrentSourceInfo.mSrcId, MEDIA2_INFO, MEDIA2_INFO_DATA_SOURCE_START, 0);
        }
@@ -2494,6 +2565,8 @@ void NuPlayer2::performPlayNextDataSource() {
    mResetting = false;
    mSourceStarted = false;

    addEndTimeMonitor();

    // Modular DRM
    if (mCrypto != NULL) {
        // decoders will be flushed before this so their mCrypto would go away on their own
@@ -2589,8 +2662,9 @@ void NuPlayer2::onSourceNotify(const sp<AMessage> &msg) {
    switch (what) {
        case Source::kWhatPrepared:
        {
            ALOGV("NuPlayer2::onSourceNotify Source::kWhatPrepared source: %p",
                  mCurrentSourceInfo.mSource.get());
            ALOGV("NuPlayer2::onSourceNotify Source::kWhatPrepared source:%p, Id(%lld)",
                  mCurrentSourceInfo.mSource.get(), (long long)srcId);
            if (srcId == mCurrentSourceInfo.mSrcId) {
                if (mCurrentSourceInfo.mSource == NULL) {
                    // This is a stale notification from a source that was
                    // asynchronously preparing when the client called reset().
@@ -2621,6 +2695,18 @@ void NuPlayer2::onSourceNotify(const sp<AMessage> &msg) {
                    }
                    driver->notifyPrepareCompleted(srcId, err);
                }
            } else if (srcId == mNextSourceInfo.mSrcId) {
                if (mNextSourceInfo.mSource == NULL) {
                    break;  // stale
                }

                sp<NuPlayer2Driver> driver = mDriver.promote();
                if (driver != NULL) {
                    int32_t err;
                    CHECK(msg->findInt32("err", &err));
                    driver->notifyPrepareCompleted(srcId, err);
                }
            }

            break;
        }
@@ -2665,8 +2751,10 @@ void NuPlayer2::onSourceNotify(const sp<AMessage> &msg) {
                    driver->notifyListener(
                            srcId, MEDIA2_INFO, MEDIA2_INFO_NOT_SEEKABLE, 0);
                }
                if (srcId == mCurrentSourceInfo.mSrcId) {
                    driver->notifyFlagsChanged(srcId, flags);
                }
            }

            if (srcId == mCurrentSourceInfo.mSrcId) {
                if ((mCurrentSourceInfo.mSourceFlags & Source::FLAG_DYNAMIC_DURATION)
@@ -3131,4 +3219,14 @@ NuPlayer2::SourceInfo::SourceInfo()
      mEndTimeUs(INT64_MAX) {
}

NuPlayer2::SourceInfo & NuPlayer2::SourceInfo::operator=(const NuPlayer2::SourceInfo &other) {
    mSource = other.mSource;
    mDataSourceType = (DATA_SOURCE_TYPE)other.mDataSourceType;
    mSrcId = other.mSrcId;
    mSourceFlags = other.mSourceFlags;
    mStartTimeUs = other.mStartTimeUs;
    mEndTimeUs = other.mEndTimeUs;
    return *this;
}

}  // namespace android
+7 −0
Original line number Diff line number Diff line
@@ -79,6 +79,7 @@ struct NuPlayer2 : public AHandler {
            int64_t seekTimeUs,
            MediaPlayer2SeekMode mode = MediaPlayer2SeekMode::SEEK_PREVIOUS_SYNC,
            bool needNotify = false);
    void rewind();

    status_t setVideoScalingMode(int32_t mode);
    status_t getTrackInfo(PlayerMessage* reply) const;
@@ -154,6 +155,8 @@ private:
        kWhatSetBufferingSettings       = 'sBuS',
        kWhatPrepareDrm                 = 'pDrm',
        kWhatReleaseDrm                 = 'rDrm',
        kWhatRewind                     = 'reWd',
        kWhatEOSMonitor                 = 'eosM',
    };

    typedef enum {
@@ -167,6 +170,7 @@ private:

    struct SourceInfo {
        SourceInfo();
        SourceInfo &operator=(const SourceInfo &);

        sp<Source> mSource;
        std::atomic<DATA_SOURCE_TYPE> mDataSourceType;
@@ -194,6 +198,7 @@ private:
    int32_t mAudioDecoderGeneration;
    int32_t mVideoDecoderGeneration;
    int32_t mRendererGeneration;
    int32_t mEOSMonitorGeneration;

    Mutex mPlayingTimeLock;
    int64_t mLastStartedPlayingTimeNs;
@@ -302,6 +307,8 @@ private:

    void notifyListener(int64_t srcId, int msg, int ext1, int ext2, const PlayerMessage *in = NULL);

    void addEndTimeMonitor();

    void handleFlushComplete(bool audio, bool isDecoder);
    void finishFlushIfPossible();

+2 −2
Original line number Diff line number Diff line
@@ -298,7 +298,7 @@ status_t NuPlayer2Driver::start_l() {
        case STATE_RUNNING:
        {
            if (mAtEOS) {
                mPlayer->seekToAsync(0);
                mPlayer->rewind();
                mAtEOS = false;
                mPositionUs = -1;
            }
@@ -859,7 +859,7 @@ void NuPlayer2Driver::notifyListener_l(
                        }
                    }
                    if (mLooping || mAutoLoop) {
                        mPlayer->seekToAsync(0);
                        mPlayer->rewind();
                        if (mAudioSink != NULL) {
                            // The renderer has stopped the sink at the end in order to play out
                            // the last little bit of audio. In looping mode, we need to restart it.
+1 −0
Original line number Diff line number Diff line
@@ -1563,6 +1563,7 @@ void NuPlayer2::Renderer::onFlush(const sp<AMessage> &msg) {
        } else {
            notifyComplete = mNotifyCompleteVideo;
            mNotifyCompleteVideo = false;
            mVideoRenderingStarted = false;
        }

        // If we're currently syncing the queues, i.e. dropping audio while