NuPlayer reset 프로세스

1.NuPlayerDriver::reset()
    mPlayer->resetAsync();//  reset

    while (mResetInProgress) { //  reset , 5 , ANR
        mCondition.wait(mLock);
    }
2.NuPlayer::resetAsync()
kWhatReset 메시지 보내기
3.kWhatReset 메시지 처리
NuPlayer::onMessageReceived
case kWhatReset:
(1) mFlushingAudio 또는 mFlushingVideo가 AWAITING_인 경우DISCONTINUITY 상태, 실행
mRenderer->resume();
    if (mRenderer != NULL) {
        // There's an edge case where the renderer owns all output
        // buffers and is paused, therefore the decoder will not read
        // more input data and will never encounter the matching
        // discontinuity. To avoid this, we resume the renderer.

        if (mFlushingAudio == AWAITING_DISCONTINUITY
                || mFlushingVideo == AWAITING_DISCONTINUITY) {
            mRenderer->resume();
        }
    }
(2)flushing 중이면reset 실행을 연기합니다
    if (mFlushingAudio != NONE || mFlushingVideo != NONE) {
        // We're currently flushing, postpone the reset until that's
        // completed.

        LOGV("postponing reset mFlushingAudio=%d, mFlushingVideo=%d",
                mFlushingAudio, mFlushingVideo);

        mResetPostponed = true; //  reset 
        break;
    }
(3) mAudioDecoder== NULL & & mVideoDecoder== NULL,reset을 실행한 경우 호출
finishReset()
(4) audio를 실행하는 flushDecoder
(5) 비디오를 실행하는 flushDecoder
(6) 변수 mResetInProgress를true로 설정
4.NuPlayer::finishReset()
(1) mSource->stop()을 수행합니다.
(2) driver->notifyResetComplete() 실행
    if (mSource != NULL) {
        mSource->stop(); //  NuPlayer::RTSPSource::stop() 
        mSource.clear();
    }

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

4.1 NuPlayer::RTSPSource::stop()
stop 함수가 메시지를 보낸 후 서버와의 연결을 끊으려면 제때에 실행해야 합니다. 그렇지 않으면 시간이 초과되어 ANR이 발생합니다.
void NuPlayer::RTSPSource::stop() {
    sp<AMessage> msg = new AMessage(kWhatDisconnect, mReflector->id());

    sp<AMessage> dummy;
    msg->postAndAwaitResponse(&dummy); //  gLooperRoster postAndAwaitResponse 
}
4.2 kWhatDisconnect 메시지 처리
void NuPlayer::RTSPSource::onMessageReceived(const sp<AMessage> &msg) {
    if (msg->what() == kWhatDisconnect) {
        uint32_t replyID;
        CHECK(msg->senderAwaitsResponse(&replyID)); //  replyID

        mDisconnectReplyID = replyID;
        finishDisconnectIfPossible(); //  
        return;
    }
4.3 NuPlayer::RTSPSource::finishDisconnectIfPossible
    if (mState != DISCONNECTED) {
        mHandler->disconnect(); //  MyHandler.h disconnect , 'abor' , 
        return;
    }
5.NuPlayerDriver::notifyResetComplete()
mResetInProgress를 false로 설정하면 1.의 대기 완료, 즉reset 실행 종료
6.NuPlayer::flushDecoder
   (audio ? mAudioDecoder : mVideoDecoder)->signalFlush();
    mRenderer->flush(audio);
7.NuPlayer::Decoder::signalFlush()
mCodec->signalFlush() 호출;ACodec의 signalFlush 함수를 호출합니다.
8.ACodec::signalFlush()
kWhatFlush 메시지 보내기
9.ACodec::UninitializedState::onMessageReceived
case ACodec::kWhatFlush:
ACodec 보내기:::kWhatFlushCompleted 메시지
10. ACodec::kWhatFlushCompleted 메시지의 처리는 NuPlayer 클래스에 있습니다.
NuPlayer::onMessageReceived
case kWhatVideoNotify:
case kWhatAudioNotify:
...
    } else if (what == ACodec::kWhatFlushCompleted) {
        bool needShutdown;

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

            mVideoLateByUs = 0;
        }

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

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

//  Decoder initiateShutdown --> ACodec::initiateShutdown() -->  kWhatShutdown  -->
//  ACodec::kWhatShutdownCompleted  -->  ACodec::kWhatShutdownCompleted 
            (audio ? mAudioDecoder : mVideoDecoder)->initiateShutdown();

            if (audio) {
                mFlushingAudio = SHUTTING_DOWN_DECODER;
            } else {
                mFlushingVideo = SHUTTING_DOWN_DECODER;
            }
        }

        finishFlushIfPossible(); //
    }

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

            CHECK_EQ((int)mFlushingAudio, (int)SHUTTING_DOWN_DECODER);
            mFlushingAudio = SHUT_DOWN;
        } else {
            mVideoDecoder.clear();

            CHECK_EQ((int)mFlushingVideo, (int)SHUTTING_DOWN_DECODER);
            mFlushingVideo = SHUT_DOWN;
        }

        finishFlushIfPossible(); //
    }
11.finishFlushIfPossible 처리
void NuPlayer::finishFlushIfPossible() {
    if (mFlushingAudio != FLUSHED && mFlushingAudio != SHUT_DOWN) {
        return;
    }

    if (mFlushingVideo != FLUSHED && mFlushingVideo != SHUT_DOWN) {
        return;
    }

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

    if (mTimeDiscontinuityPending) {
        mRenderer->signalTimeDiscontinuity(); //  
        mTimeDiscontinuityPending = false;
    }

// NuPlayer::Decoder::signalResume --> ACodec::signalResume -->  kWhatResume  -->
// ACodec::ExecutingState::resume --> ACodec::ExecutingState::submitOutputBuffers -->
// ACodec::BaseState::postFillThisBuffer --> kWhatInputBufferFilled -->
// ACodec::BaseState::onInputBufferFilled
    if (mAudioDecoder != NULL) {
        mAudioDecoder->signalResume();
    }

    if (mVideoDecoder != NULL) {
        mVideoDecoder->signalResume();
    }

    mFlushingAudio = NONE;
    mFlushingVideo = NONE;

    if (mResetInProgress) { // 3.(6) true 
        LOGV("reset completed");

        mResetInProgress = false;
        finishReset(); // reset , 4,5 
    } else if (mResetPostponed) { //  3.(2) reset, kWhatReset 
        (new AMessage(kWhatReset, id()))->post();
        mResetPostponed = false;
    } else if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
        postScanSources();
    }
}

좋은 웹페이지 즐겨찾기