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

Commit c213b812 authored by Andreas Huber's avatar Andreas Huber Committed by Android (Google) Code Review
Browse files

Merge "Properly shutdown the decoders on a reset() in NuPlayer's implementation."

parents c2f95fba 1aef211b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ 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,
};
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ bool NuPlayer::HTTPLiveSource::feedMoreTSData() {
            break;
        } else if (n < 0) {
            LOGI("input data EOS reached.");
            mTSParser->signalEOS(ERROR_END_OF_STREAM);
            mTSParser->signalEOS(n);
            mEOS = true;
            break;
        } else {
+145 −56
Original line number Diff line number Diff line
@@ -45,8 +45,11 @@ NuPlayer::NuPlayer()
    : mAudioEOS(false),
      mVideoEOS(false),
      mScanSourcesPending(false),
      mScanSourcesGeneration(0),
      mFlushingAudio(NONE),
      mFlushingVideo(NONE) {
      mFlushingVideo(NONE),
      mResetInProgress(false),
      mResetPostponed(false) {
}

NuPlayer::~NuPlayer() {
@@ -87,18 +90,22 @@ void NuPlayer::start() {
    (new AMessage(kWhatStart, id()))->post();
}

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

// static
bool NuPlayer::IsFlushingState(FlushStatus state, bool *formatChange) {
bool NuPlayer::IsFlushingState(FlushStatus state, bool *needShutdown) {
    switch (state) {
        case FLUSHING_DECODER:
            if (formatChange != NULL) {
                *formatChange = false;
            if (needShutdown != NULL) {
                *needShutdown = false;
            }
            return true;

        case FLUSHING_DECODER_FORMATCHANGE:
            if (formatChange != NULL) {
                *formatChange = true;
        case FLUSHING_DECODER_SHUTDOWN:
            if (needShutdown != NULL) {
                *needShutdown = true;
            }
            return true;

@@ -111,7 +118,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
    switch (msg->what()) {
        case kWhatSetDataSource:
        {
            LOGI("kWhatSetDataSource");
            LOGV("kWhatSetDataSource");

            CHECK(mSource == NULL);

@@ -124,7 +131,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatSetVideoSurface:
        {
            LOGI("kWhatSetVideoSurface");
            LOGV("kWhatSetVideoSurface");

            sp<RefBase> obj;
            CHECK(msg->findObject("surface", &obj));
@@ -135,7 +142,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatSetAudioSink:
        {
            LOGI("kWhatSetAudioSink");
            LOGV("kWhatSetAudioSink");

            sp<RefBase> obj;
            CHECK(msg->findObject("sink", &obj));
@@ -146,6 +153,9 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

        case kWhatStart:
        {
            mAudioEOS = false;
            mVideoEOS = false;

            mSource->start();

            mRenderer = new Renderer(
@@ -154,13 +164,19 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

            looper()->registerHandler(mRenderer);

            (new AMessage(kWhatScanSources, id()))->post();
            mScanSourcesPending = true;
            postScanSources();
            break;
        }

        case kWhatScanSources:
        {
            int32_t generation;
            CHECK(msg->findInt32("generation", &generation));
            if (generation != mScanSourcesGeneration) {
                // Drop obsolete msg.
                break;
            }

            mScanSourcesPending = false;

            instantiateDecoder(false, &mVideoDecoder);
@@ -170,6 +186,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
            }

            if (!mSource->feedMoreTSData()) {
                if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
                    // We're not currently decoding anything (no audio or
                    // video tracks found) and we just ran out of input data.
                    notifyListener(MEDIA_PLAYBACK_COMPLETE, 0, 0);
                }
                break;
            }

@@ -203,20 +224,20 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
            } else if (what == ACodec::kWhatEOS) {
                mRenderer->queueEOS(audio, ERROR_END_OF_STREAM);
            } else if (what == ACodec::kWhatFlushCompleted) {
                bool formatChange;
                bool needShutdown;

                if (audio) {
                    CHECK(IsFlushingState(mFlushingAudio, &formatChange));
                    CHECK(IsFlushingState(mFlushingAudio, &needShutdown));
                    mFlushingAudio = FLUSHED;
                } else {
                    CHECK(IsFlushingState(mFlushingVideo, &formatChange));
                    CHECK(IsFlushingState(mFlushingVideo, &needShutdown));
                    mFlushingVideo = FLUSHED;
                }

                LOGI("decoder %s flush completed", audio ? "audio" : "video");
                LOGV("decoder %s flush completed", audio ? "audio" : "video");

                if (formatChange) {
                    LOGI("initiating %s decoder shutdown",
                if (needShutdown) {
                    LOGV("initiating %s decoder shutdown",
                         audio ? "audio" : "video");

                    (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();
@@ -238,7 +259,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                int32_t sampleRate;
                CHECK(codecRequest->findInt32("sample-rate", &sampleRate));

                LOGI("Audio output format changed to %d Hz, %d channels",
                LOGV("Audio output format changed to %d Hz, %d channels",
                     sampleRate, numChannels);

                mAudioSink->close();
@@ -247,7 +268,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {

                mRenderer->signalAudioSinkChanged();
            } else if (what == ACodec::kWhatShutdownCompleted) {
                LOGI("%s shutdown completed", audio ? "audio" : "video");
                LOGV("%s shutdown completed", audio ? "audio" : "video");
                if (audio) {
                    mAudioDecoder.clear();

@@ -285,7 +306,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                    mVideoEOS = true;
                }

                LOGI("reached %s EOS", audio ? "audio" : "video");
                LOGV("reached %s EOS", audio ? "audio" : "video");

                if ((mAudioEOS || mAudioDecoder == NULL)
                        && (mVideoEOS || mVideoDecoder == NULL)) {
@@ -297,7 +318,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
                int32_t audio;
                CHECK(msg->findInt32("audio", &audio));

                LOGI("renderer %s flush completed.", audio ? "audio" : "video");
                LOGV("renderer %s flush completed.", audio ? "audio" : "video");
            }
            break;
        }
@@ -307,6 +328,37 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
            break;
        }

        case kWhatReset:
        {
            LOGV("kWhatReset");

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

                LOGV("postponing reset");

                mResetPostponed = true;
                break;
            }

            if (mAudioDecoder == NULL && mVideoDecoder == NULL) {
                finishReset();
                break;
            }

            if (mAudioDecoder != NULL) {
                flushDecoder(true /* audio */, true /* needShutdown */);
            }

            if (mVideoDecoder != NULL) {
                flushDecoder(false /* audio */, true /* needShutdown */);
            }

            mResetInProgress = true;
            break;
        }

        default:
            TRESPASS();
            break;
@@ -322,7 +374,7 @@ void NuPlayer::finishFlushIfPossible() {
        return;
    }

    LOGI("both audio and video are flushed now.");
    LOGV("both audio and video are flushed now.");

    mRenderer->signalTimeDiscontinuity();

@@ -343,10 +395,39 @@ void NuPlayer::finishFlushIfPossible() {
    mFlushingAudio = NONE;
    mFlushingVideo = NONE;

    if (scanSourcesAgain && !mScanSourcesPending) {
        mScanSourcesPending = true;
        (new AMessage(kWhatScanSources, id()))->post();
    if (mResetInProgress) {
        LOGV("reset completed");

        mResetInProgress = false;
        finishReset();
    } else if (mResetPostponed) {
        (new AMessage(kWhatReset, id()))->post();
        mResetPostponed = false;
    } else if (scanSourcesAgain) {
        postScanSources();
    }
}

void NuPlayer::finishReset() {
    CHECK(mAudioDecoder == NULL);
    CHECK(mVideoDecoder == NULL);

    mRenderer.clear();
    mSource.clear();

    notifyListener(MEDIA_RESET_COMPLETE, 0, 0);
}

void NuPlayer::postScanSources() {
    if (mScanSourcesPending) {
        return;
    }

    sp<AMessage> msg = new AMessage(kWhatScanSources, id());
    msg->setInt32("generation", mScanSourcesGeneration);
    msg->post();

    mScanSourcesPending = true;
}

status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
@@ -396,37 +477,10 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
            bool formatChange =
                type == ATSParser::DISCONTINUITY_FORMATCHANGE;

            LOGI("%s discontinuity (formatChange=%d)",
            LOGV("%s discontinuity (formatChange=%d)",
                 audio ? "audio" : "video", formatChange);

            (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
            mRenderer->flush(audio);

            if (audio) {
                CHECK(mFlushingAudio == NONE
                        || mFlushingAudio == AWAITING_DISCONTINUITY);

                mFlushingAudio = formatChange
                    ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;

                if (mFlushingVideo == NONE) {
                    mFlushingVideo = (mVideoDecoder != NULL)
                        ? AWAITING_DISCONTINUITY
                        : FLUSHED;
                }
            } else {
                CHECK(mFlushingVideo == NONE
                        || mFlushingVideo == AWAITING_DISCONTINUITY);

                mFlushingVideo = formatChange
                    ? FLUSHING_DECODER_FORMATCHANGE : FLUSHING_DECODER;

                if (mFlushingAudio == NONE) {
                    mFlushingAudio = (mAudioDecoder != NULL)
                        ? AWAITING_DISCONTINUITY
                        : FLUSHED;
                }
            }
            flushDecoder(audio, formatChange);
        }

        reply->setInt32("err", err);
@@ -439,7 +493,7 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
#if 0
    int64_t mediaTimeUs;
    CHECK(accessUnit->meta()->findInt64("timeUs", &mediaTimeUs));
    LOGI("feeding %s input buffer at media time %.2f secs",
    LOGV("feeding %s input buffer at media time %.2f secs",
         audio ? "audio" : "video",
         mediaTimeUs / 1E6);
#endif
@@ -478,4 +532,39 @@ void NuPlayer::notifyListener(int msg, int ext1, int ext2) {
    listener->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;

    (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
    mRenderer->flush(audio);

    FlushStatus newStatus =
        needShutdown ? FLUSHING_DECODER_SHUTDOWN : FLUSHING_DECODER;

    if (audio) {
        CHECK(mFlushingAudio == NONE
                || mFlushingAudio == AWAITING_DISCONTINUITY);

        mFlushingAudio = newStatus;

        if (mFlushingVideo == NONE) {
            mFlushingVideo = (mVideoDecoder != NULL)
                ? AWAITING_DISCONTINUITY
                : FLUSHED;
        }
    } else {
        CHECK(mFlushingVideo == NONE
                || mFlushingVideo == AWAITING_DISCONTINUITY);

        mFlushingVideo = newStatus;

        if (mFlushingAudio == NONE) {
            mFlushingAudio = (mAudioDecoder != NULL)
                ? AWAITING_DISCONTINUITY
                : FLUSHED;
        }
    }
}

}  // namespace android
+15 −3
Original line number Diff line number Diff line
@@ -40,6 +40,10 @@ 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 resetAsync();

protected:
    virtual ~NuPlayer();

@@ -63,6 +67,7 @@ private:
        kWhatVideoNotify,
        kWhatAudioNotify,
        kWhatRendererNotify,
        kWhatReset,
    };

    wp<MediaPlayerBase> mListener;
@@ -73,17 +78,17 @@ private:
    sp<Decoder> mAudioDecoder;
    sp<Renderer> mRenderer;

    bool mEOS;
    bool mAudioEOS;
    bool mVideoEOS;

    bool mScanSourcesPending;
    int32_t mScanSourcesGeneration;

    enum FlushStatus {
        NONE,
        AWAITING_DISCONTINUITY,
        FLUSHING_DECODER,
        FLUSHING_DECODER_FORMATCHANGE,
        FLUSHING_DECODER_SHUTDOWN,
        SHUTTING_DOWN_DECODER,
        FLUSHED,
        SHUT_DOWN,
@@ -91,6 +96,8 @@ private:

    FlushStatus mFlushingAudio;
    FlushStatus mFlushingVideo;
    bool mResetInProgress;
    bool mResetPostponed;

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

@@ -101,7 +108,12 @@ private:

    void finishFlushIfPossible();

    static bool IsFlushingState(FlushStatus state, bool *formatChange = NULL);
    void flushDecoder(bool audio, bool needShutdown);

    static bool IsFlushingState(FlushStatus state, bool *needShutdown = NULL);

    void finishReset();
    void postScanSources();

    DISALLOW_EVIL_CONSTRUCTORS(NuPlayer);
};
+24 −1
Original line number Diff line number Diff line
@@ -22,12 +22,14 @@

#include "NuPlayer.h"

#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/ALooper.h>

namespace android {

NuPlayerDriver::NuPlayerDriver()
    : mLooper(new ALooper),
    : mResetInProgress(false),
      mLooper(new ALooper),
      mPlayer(false) {
    mLooper->setName("NuPlayerDriver Looper");

@@ -121,6 +123,15 @@ status_t NuPlayerDriver::getDuration(int *msec) {
}

status_t NuPlayerDriver::reset() {
    Mutex::Autolock autoLock(mLock);
    mResetInProgress = true;

    mPlayer->resetAsync();

    while (mResetInProgress) {
        mCondition.wait(mLock);
    }

    return OK;
}

@@ -145,4 +156,16 @@ status_t NuPlayerDriver::getMetadata(
    return INVALID_OPERATION;
}

void NuPlayerDriver::sendEvent(int msg, int ext1, int ext2) {
    if (msg != MEDIA_RESET_COMPLETE) {
        MediaPlayerInterface::sendEvent(msg, ext1, ext2);
        return;
    }

    Mutex::Autolock autoLock(mLock);
    CHECK(mResetInProgress);
    mResetInProgress = false;
    mCondition.broadcast();
}

}  // namespace android
Loading