NuPlayer 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();
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
🦸♂️AVFoundation 튜토리얼: iOS에서 비디오에 효과를 적용하는 방법아래에서 효과를 적용하는 방법에 대한 간단한 가이드를 찾을 수 있습니다. Core Image를 사용하면 사용자 정의 효과를 생성하기 위해 서로 다른 필터(CiFilter)를 함께 연결할 수 있습니다. 또한 GPU(그...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.