diff options
Diffstat (limited to 'media/libmediaplayerservice/nuplayer/NuPlayer.cpp')
-rw-r--r-- | media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 169 |
1 files changed, 146 insertions, 23 deletions
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 26532d7..1835101 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -56,6 +56,7 @@ #include "ESDS.h" #include <media/stagefright/Utils.h> +#include "mediaplayerservice/AVNuExtensions.h" namespace android { @@ -130,6 +131,23 @@ private: DISALLOW_EVIL_CONSTRUCTORS(FlushDecoderAction); }; +struct NuPlayer::InstantiateDecoderAction : public Action { + InstantiateDecoderAction(bool audio, sp<DecoderBase> *decoder) + : mAudio(audio), + mdecoder(decoder) { + } + + virtual void execute(NuPlayer *player) { + player->instantiateDecoder(mAudio, mdecoder); + } + +private: + bool mAudio; + sp<DecoderBase> *mdecoder; + + DISALLOW_EVIL_CONSTRUCTORS(InstantiateDecoderAction); +}; + struct NuPlayer::PostMessageAction : public Action { PostMessageAction(const sp<AMessage> &msg) : mMessage(msg) { @@ -171,6 +189,7 @@ NuPlayer::NuPlayer(pid_t pid) mPID(pid), mSourceFlags(0), mOffloadAudio(false), + mOffloadDecodedPCM(false), mAudioDecoderGeneration(0), mVideoDecoderGeneration(0), mRendererGeneration(0), @@ -188,6 +207,7 @@ NuPlayer::NuPlayer(pid_t pid) mPlaybackSettings(AUDIO_PLAYBACK_RATE_DEFAULT), mVideoFpsHint(-1.f), mStarted(false), + mResetting(false), mSourceStarted(false), mPaused(false), mPausedByClient(false), @@ -216,7 +236,7 @@ void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) { msg->post(); } -static bool IsHTTPLiveURL(const char *url) { +bool NuPlayer::IsHTTPLiveURL(const char *url) { if (!strncasecmp("http://", url, 7) || !strncasecmp("https://", url, 8) || !strncasecmp("file://", url, 7)) { @@ -640,7 +660,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { // When mStarted is true, mSource must have been set. if (mSource == NULL || !mStarted || mSource->getFormat(false /* audio */) == NULL // NOTE: mVideoDecoder's mSurface is always non-null - || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK)) { +#ifndef CANNOT_SET_SURFACE_WITHOUT_A_FLUSH + || (mVideoDecoder != NULL && mVideoDecoder->setVideoSurface(surface) == OK) +#endif + ) { performSetSurface(surface); break; } @@ -912,10 +935,21 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { audio ? "audio" : "video", formatChange); if (formatChange) { - mDeferredActions.push_back( - new FlushDecoderAction( + int32_t seamlessChange = 0; + if (msg->findInt32("video-seamlessChange", &seamlessChange) && seamlessChange) { + ALOGE("video decoder seamlessChange in smooth streaming mode, " + "flush the video decoder"); + mDeferredActions.push_back( + new FlushDecoderAction(FLUSH_CMD_NONE, FLUSH_CMD_FLUSH)); + mDeferredActions.push_back(new ResumeDecoderAction(false)); + processDeferredActions(); + break; + } else { + mDeferredActions.push_back( + new FlushDecoderAction( audio ? FLUSH_CMD_SHUTDOWN : FLUSH_CMD_NONE, audio ? FLUSH_CMD_NONE : FLUSH_CMD_SHUTDOWN)); + } } mDeferredActions.push_back( @@ -1098,6 +1132,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { int32_t reason; CHECK(msg->findInt32("reason", &reason)); ALOGV("Tear down audio with reason %d.", reason); + mAudioDecoder->pause(); mAudioDecoder.clear(); ++mAudioDecoderGeneration; bool needsToCreateAudioDecoder = true; @@ -1145,10 +1180,17 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { { ALOGV("kWhatReset"); + mResetting = true; + + if (mAudioDecoder != NULL && mFlushingAudio == NONE) { + mDeferredActions.push_back( + new FlushDecoderAction( + FLUSH_CMD_SHUTDOWN /* audio */, + FLUSH_CMD_SHUTDOWN /* video */)); + } + mDeferredActions.push_back( - new FlushDecoderAction( - FLUSH_CMD_SHUTDOWN /* audio */, - FLUSH_CMD_SHUTDOWN /* video */)); + new SimpleAction(&NuPlayer::closeAudioSink)); mDeferredActions.push_back( new SimpleAction(&NuPlayer::performReset)); @@ -1227,7 +1269,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } void NuPlayer::onResume() { - if (!mPaused) { + if (!mPaused || mResetting) { + ALOGD_IF(mResetting, "resetting, onResume discarded"); return; } mPaused = false; @@ -1236,6 +1279,13 @@ void NuPlayer::onResume() { } else { ALOGW("resume called when source is gone or not set"); } + if (mOffloadAudio && !mOffloadDecodedPCM) { + // Resuming after a pause timed out event, check if can continue with offload + sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); + sp<AMessage> format = mSource->getFormat(true /*audio*/); + const bool hasVideo = (videoFormat != NULL); + tryOpenAudioSinkForOffload(format, hasVideo); + } // |mAudioDecoder| may have been released due to the pause timeout, so re-create it if // needed. if (audioDecoderStillNeeded() && mAudioDecoder == NULL) { @@ -1290,6 +1340,7 @@ void NuPlayer::onStart(int64_t startPositionUs) { } mOffloadAudio = false; + mOffloadDecodedPCM = false; mAudioEOS = false; mVideoEOS = false; mStarted = true; @@ -1300,7 +1351,10 @@ void NuPlayer::onStart(int64_t startPositionUs) { flags |= Renderer::FLAG_REAL_TIME; } + ALOGV("onStart"); sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); + AVNuUtils::get()->setSourcePCMFormat(audioMeta); + audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; if (mAudioSink != NULL) { streamType = mAudioSink->getAudioStreamType(); @@ -1310,6 +1364,10 @@ void NuPlayer::onStart(int64_t startPositionUs) { mOffloadAudio = canOffloadStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType); + if (!mOffloadAudio && (audioMeta != NULL)) { + mOffloadDecodedPCM = mOffloadAudio = canOffloadDecodedPCMStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType); + } + if (mOffloadAudio) { flags |= Renderer::FLAG_OFFLOAD_AUDIO; } @@ -1317,7 +1375,7 @@ void NuPlayer::onStart(int64_t startPositionUs) { sp<AMessage> notify = new AMessage(kWhatRendererNotify, this); ++mRendererGeneration; notify->setInt32("generation", mRendererGeneration); - mRenderer = new Renderer(mAudioSink, notify, flags); + mRenderer = AVNuFactory::get()->createRenderer(mAudioSink, notify, flags); mRendererLooper = new ALooper; mRendererLooper->setName("NuPlayerRenderer"); mRendererLooper->start(false, false, ANDROID_PRIORITY_AUDIO); @@ -1444,15 +1502,22 @@ void NuPlayer::postScanSources() { void NuPlayer::tryOpenAudioSinkForOffload(const sp<AMessage> &format, bool hasVideo) { // Note: This is called early in NuPlayer to determine whether offloading // is possible; otherwise the decoders call the renderer openAudioSink directly. - + sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); + sp<AMessage> pcmFormat; + if (mOffloadDecodedPCM) { + sp<MetaData> pcm = AVNuUtils::get()->createPCMMetaFromSource(audioMeta); + audioMeta = pcm; + convertMetaDataToMessage(pcm, &pcmFormat); + } status_t err = mRenderer->openAudioSink( - format, true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, &mOffloadAudio); + mOffloadDecodedPCM ? pcmFormat : format, + true /* offloadOnly */, hasVideo, AUDIO_OUTPUT_FLAG_NONE, + &mOffloadAudio, mSource->isStreaming()); if (err != OK) { // Any failure we turn off mOffloadAudio. mOffloadAudio = false; + mOffloadDecodedPCM = false; } else if (mOffloadAudio) { - sp<MetaData> audioMeta = - mSource->getFormatMeta(true /* audio */); sendMetaDataToHal(mAudioSink, audioMeta); } } @@ -1469,6 +1534,7 @@ void NuPlayer::determineAudioModeChange() { if (mRenderer == NULL) { ALOGW("No renderer can be used to determine audio mode. Use non-offload for safety."); mOffloadAudio = false; + mOffloadDecodedPCM = false; return; } @@ -1476,8 +1542,11 @@ void NuPlayer::determineAudioModeChange() { sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); audio_stream_type_t streamType = mAudioSink->getAudioStreamType(); const bool hasVideo = (videoFormat != NULL); - const bool canOffload = canOffloadStream( + bool canOffload = canOffloadStream( audioMeta, hasVideo, mSource->isStreaming(), streamType); + if (!canOffload) { + mOffloadDecodedPCM = canOffload = canOffloadDecodedPCMStream(audioMeta, (videoFormat != NULL), mSource->isStreaming(), streamType); + } if (canOffload) { if (!mOffloadAudio) { mRenderer->signalEnableOffloadAudio(); @@ -1499,7 +1568,10 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder) { if (*decoder != NULL || (audio && mFlushingAudio == SHUT_DOWN)) { return OK; } - + if (mSource == NULL) { + ALOGD("%s Ignore instantiate decoder after clearing source", __func__); + return INVALID_OPERATION; + } sp<AMessage> format = mSource->getFormat(audio); if (format == NULL) { @@ -1537,12 +1609,17 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder) { notify->setInt32("generation", mAudioDecoderGeneration); determineAudioModeChange(); - if (mOffloadAudio) { + + if (AVNuUtils::get()->isRAWFormat(format)) { + AVNuUtils::get()->setPCMFormat(format, + AVNuUtils::get()->getKeyPCMFormat(mSource->getFormatMeta(true /* audio */))); + } + if (mOffloadAudio && !ifDecodedPCMOffload()) { const bool hasVideo = (mSource->getFormat(false /*audio */) != NULL); format->setInt32("has-video", hasVideo); - *decoder = new DecoderPassThrough(notify, mSource, mRenderer); + *decoder = AVNuFactory::get()->createPassThruDecoder(notify, mSource, mRenderer); } else { - *decoder = new Decoder(notify, mSource, mPID, mRenderer); + *decoder = AVNuFactory::get()->createDecoder(notify, mSource, mPID, mRenderer); } } else { sp<AMessage> notify = new AMessage(kWhatVideoNotify, this); @@ -1567,7 +1644,8 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<DecoderBase> *decoder) { (*decoder)->configure(format); // allocate buffers to decrypt widevine source buffers - if (!audio && (mSourceFlags & Source::FLAG_SECURE)) { + if (!audio && ((mSourceFlags & Source::FLAG_SECURE) || + (mSourceFlags & Source::FLAG_USE_SET_BUFFERS))) { Vector<sp<ABuffer> > inputBufs; CHECK_EQ((*decoder)->getInputBuffers(&inputBufs), (status_t)OK); @@ -1680,6 +1758,18 @@ void NuPlayer::flushDecoder(bool audio, bool needShutdown) { return; } + FlushStatus *state = audio ? &mFlushingAudio : &mFlushingVideo; + + bool inShutdown = *state != NONE && + *state != FLUSHING_DECODER && + *state != FLUSHED; + + // Reject flush if the decoder state is not one of the above + if (inShutdown) { + ALOGI("flush %s called while in shutdown", audio ? "audio" : "video"); + return; + } + // Make sure we don't continue to scan sources until we finish flushing. ++mScanSourcesGeneration; if (mScanSourcesPending) { @@ -1898,9 +1988,6 @@ void NuPlayer::performDecoderFlush(FlushCommand audio, FlushCommand video) { void NuPlayer::performReset() { ALOGV("performReset"); - CHECK(mAudioDecoder == NULL); - CHECK(mVideoDecoder == NULL); - cancelPollDuration(); ++mScanSourcesGeneration; @@ -1930,6 +2017,7 @@ void NuPlayer::performReset() { } mStarted = false; + mResetting = false; mSourceStarted = false; } @@ -2190,7 +2278,7 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { int posMs; int64_t timeUs, posUs; driver->getCurrentPosition(&posMs); - posUs = posMs * 1000; + posUs = (int64_t) posMs * 1000ll; CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); if (posUs < timeUs) { @@ -2223,6 +2311,13 @@ void NuPlayer::onSourceNotify(const sp<AMessage> &msg) { break; } + case Source::kWhatRTCPByeReceived: + { + ALOGV("notify the client that Bye message is received"); + notifyListener(MEDIA_INFO, 2000, 0); + break; + } + default: TRESPASS(); } @@ -2368,4 +2463,32 @@ void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) { TRESPASS(); } +bool NuPlayer::ifDecodedPCMOffload() { + return mOffloadDecodedPCM; +} + +void NuPlayer::setDecodedPcmOffload(bool decodePcmOffload) { + mOffloadDecodedPCM = decodePcmOffload; +} + +bool NuPlayer::canOffloadDecodedPCMStream(const sp<MetaData> audioMeta, + bool hasVideo, bool isStreaming, audio_stream_type_t streamType) { + const char *mime = NULL; + + //For offloading decoded content + if (!mOffloadAudio && (audioMeta != NULL)) { + audioMeta->findCString(kKeyMIMEType, &mime); + sp<MetaData> audioPCMMeta = + AVNuUtils::get()->createPCMMetaFromSource(audioMeta); + + ALOGI("canOffloadDecodedPCMStream"); + audioPCMMeta->dumpToLog(); + mOffloadDecodedPCM = + ((mime && !AVNuUtils::get()->pcmOffloadException(audioMeta)) && + canOffloadStream(audioPCMMeta, hasVideo, isStreaming, streamType)); + ALOGI("PCM offload decided: %d", mOffloadDecodedPCM); + } + return mOffloadDecodedPCM; +} + } // namespace android |