Loading media/libmediaplayerservice/nuplayer/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ LOCAL_SRC_FILES:= \ HTTPLiveSource.cpp \ NuPlayer.cpp \ NuPlayerDecoder.cpp \ NuPlayerDecoderPassThrough.cpp \ NuPlayerDriver.cpp \ NuPlayerRenderer.cpp \ NuPlayerStreamListener.cpp \ Loading media/libmediaplayerservice/nuplayer/NuPlayer.cpp +114 −14 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "HTTPLiveSource.h" #include "NuPlayerDecoder.h" #include "NuPlayerDecoderPassThrough.h" #include "NuPlayerDriver.h" #include "NuPlayerRenderer.h" #include "NuPlayerSource.h" Loading Loading @@ -143,6 +144,7 @@ NuPlayer::NuPlayer() : mUIDValid(false), mSourceFlags(0), mVideoIsAVC(false), mOffloadAudio(false), mAudioEOS(false), mVideoEOS(false), mScanSourcesPending(false), Loading Loading @@ -500,6 +502,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { ALOGV("kWhatStart"); mVideoIsAVC = false; mOffloadAudio = false; mAudioEOS = false; mVideoEOS = false; mSkipRenderingAudioUntilMediaTimeUs = -1; Loading @@ -517,6 +520,21 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { flags |= Renderer::FLAG_REAL_TIME; } sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; if (mAudioSink != NULL) { streamType = mAudioSink->getAudioStreamType(); } sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); mOffloadAudio = canOffloadStream(audioMeta, (videoFormat != NULL), true /* is_streaming */, streamType); if (mOffloadAudio) { flags |= Renderer::FLAG_OFFLOAD_AUDIO; } mRenderer = new Renderer( mAudioSink, new AMessage(kWhatRendererNotify, id()), Loading Loading @@ -661,7 +679,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mAudioSink->close(); audio_output_flags_t flags; uint32_t flags; int64_t durationUs; // FIXME: we should handle the case where the video decoder // is created after we receive the format change indication. Loading @@ -682,6 +700,80 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; } if (mOffloadAudio) { audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; AString mime; CHECK(format->findString("mime", &mime)); status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str()); if (err != OK) { ALOGE("Couldn't map mime \"%s\" to a valid " "audio_format", mime.c_str()); mOffloadAudio = false; } else { ALOGV("Mime \"%s\" mapped to audio_format 0x%x", mime.c_str(), audioFormat); flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; offloadInfo.duration_us = -1; format->findInt64( "durationUs", &offloadInfo.duration_us); int avgBitRate = -1; format->findInt32("bit-rate", &avgBitRate); offloadInfo.sample_rate = sampleRate; offloadInfo.channel_mask = channelMask; offloadInfo.format = audioFormat; offloadInfo.stream_type = AUDIO_STREAM_MUSIC; offloadInfo.bit_rate = avgBitRate; offloadInfo.has_video = (mVideoDecoder != NULL); offloadInfo.is_streaming = true; err = mAudioSink->open( sampleRate, numChannels, (audio_channel_mask_t)channelMask, audioFormat, 8 /* bufferCount */, &NuPlayer::Renderer::AudioSinkCallback, mRenderer.get(), (audio_output_flags_t)flags, &offloadInfo); if (err == OK) { // If the playback is offloaded to h/w, we pass // the HAL some metadata information. // We don't want to do this for PCM because it // will be going through the AudioFlinger mixer // before reaching the hardware. sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); sendMetaDataToHal(mAudioSink, audioMeta); err = mAudioSink->start(); } } if (err != OK) { // Clean up, fall back to non offload mode. mAudioSink->close(); mAudioDecoder.clear(); mRenderer->signalDisableOffloadAudio(); mOffloadAudio = false; instantiateDecoder( true /* audio */, &mAudioDecoder); } } if (!mOffloadAudio) { flags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; CHECK_EQ(mAudioSink->open( sampleRate, numChannels, Loading @@ -690,9 +782,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { 8 /* bufferCount */, NULL, NULL, flags), (audio_output_flags_t)flags), (status_t)OK); mAudioSink->start(); } mRenderer->signalAudioSinkChanged(); } else { Loading Loading @@ -968,8 +1061,15 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, id()); *decoder = audio ? new Decoder(notify) : new Decoder(notify, mNativeWindow); if (audio) { if (mOffloadAudio) { *decoder = new DecoderPassThrough(notify); } else { *decoder = new Decoder(notify); } } else { *decoder = new Decoder(notify, mNativeWindow); } (*decoder)->init(); (*decoder)->configure(format); Loading media/libmediaplayerservice/nuplayer/NuPlayer.h +2 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ public: private: struct Decoder; struct DecoderPassThrough; struct CCDecoder; struct GenericSource; struct HTTPLiveSource; Loading Loading @@ -120,6 +121,7 @@ private: sp<MediaPlayerBase::AudioSink> mAudioSink; sp<Decoder> mVideoDecoder; bool mVideoIsAVC; bool mOffloadAudio; sp<Decoder> mAudioDecoder; sp<CCDecoder> mCCDecoder; sp<Renderer> mRenderer; Loading media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h +6 −6 Original line number Diff line number Diff line Loading @@ -31,14 +31,14 @@ struct NuPlayer::Decoder : public AHandler { Decoder(const sp<AMessage> ¬ify, const sp<NativeWindowWrapper> &nativeWindow = NULL); void configure(const sp<AMessage> &format); void init(); virtual void configure(const sp<AMessage> &format); virtual void init(); void signalFlush(); void signalResume(); void initiateShutdown(); virtual void signalFlush(); virtual void signalResume(); virtual void initiateShutdown(); bool supportsSeamlessFormatChange(const sp<AMessage> &to) const; virtual bool supportsSeamlessFormatChange(const sp<AMessage> &to) const; enum { kWhatFillThisBuffer = 'flTB', Loading media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp 0 → 100644 +237 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "NuPlayerDecoderPassThrough" #include <utils/Log.h> #include <inttypes.h> #include "NuPlayerDecoderPassThrough.h" #include <media/ICrypto.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> namespace android { static const int kMaxPendingBuffers = 10; NuPlayer::DecoderPassThrough::DecoderPassThrough( const sp<AMessage> ¬ify) : Decoder(notify), mNotify(notify), mBufferGeneration(0), mReachedEOS(true), mPendingBuffers(0), mComponentName("pass through decoder") { mDecoderLooper = new ALooper; mDecoderLooper->setName("NuPlayerDecoderPassThrough"); mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO); } NuPlayer::DecoderPassThrough::~DecoderPassThrough() { } void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) { sp<AMessage> msg = new AMessage(kWhatConfigure, id()); msg->setMessage("format", format); msg->post(); } void NuPlayer::DecoderPassThrough::init() { mDecoderLooper->registerHandler(this); } void NuPlayer::DecoderPassThrough::signalFlush() { (new AMessage(kWhatFlush, id()))->post(); } void NuPlayer::DecoderPassThrough::signalResume() { (new AMessage(kWhatResume, id()))->post(); } void NuPlayer::DecoderPassThrough::initiateShutdown() { (new AMessage(kWhatShutdown, id()))->post(); } bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange( const sp<AMessage> & /* targetFormat */) const { return true; } void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) { ALOGV("[%s] onConfigure", mComponentName.c_str()); mPendingBuffers = 0; mReachedEOS = false; ++mBufferGeneration; requestABuffer(); sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatOutputFormatChanged); notify->setMessage("format", format); notify->post(); } bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) { int32_t generation; CHECK(msg->findInt32("generation", &generation)); return generation != mBufferGeneration; } void NuPlayer::DecoderPassThrough::requestABuffer() { if (mPendingBuffers >= kMaxPendingBuffers || mReachedEOS) { ALOGV("[%s] mReachedEOS=%d, max pending buffers(%d:%d)", mComponentName.c_str(), (mReachedEOS ? 1 : 0), mPendingBuffers, kMaxPendingBuffers); return; } sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id()); reply->setInt32("generation", mBufferGeneration); sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatFillThisBuffer); notify->setMessage("reply", reply); notify->post(); mPendingBuffers++; sp<AMessage> message = new AMessage(kWhatRequestABuffer, id()); message->setInt32("generation", mBufferGeneration); message->post(); return; } void android::NuPlayer::DecoderPassThrough::onInputBufferFilled( const sp<AMessage> &msg) { if (mReachedEOS) { return; } sp<ABuffer> buffer; msg->findBuffer("buffer", &buffer); if (buffer == NULL) { mReachedEOS = true; sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatEOS); notify->setInt32("err", ERROR_END_OF_STREAM); notify->post(); return; } sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id()); reply->setInt32("generation", mBufferGeneration); sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatDrainThisBuffer); notify->setBuffer("buffer", buffer); notify->setMessage("reply", reply); notify->post(); } void NuPlayer::DecoderPassThrough::onBufferConsumed() { mPendingBuffers--; sp<AMessage> message = new AMessage(kWhatRequestABuffer, id()); message->setInt32("generation", mBufferGeneration); message->post(); } void NuPlayer::DecoderPassThrough::onFlush() { ++mBufferGeneration; sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatFlushCompleted); notify->post(); mPendingBuffers = 0; mReachedEOS = false; } void NuPlayer::DecoderPassThrough::onShutdown() { ++mBufferGeneration; sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatShutdownCompleted); notify->post(); mReachedEOS = true; } void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) { ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str()); switch (msg->what()) { case kWhatConfigure: { sp<AMessage> format; CHECK(msg->findMessage("format", &format)); onConfigure(format); break; } case kWhatRequestABuffer: { if (!isStaleReply(msg)) { requestABuffer(); } break; } case kWhatInputBufferFilled: { if (!isStaleReply(msg)) { onInputBufferFilled(msg); } break; } case kWhatBufferConsumed: { if (!isStaleReply(msg)) { onBufferConsumed(); } break; } case kWhatFlush: { onFlush(); break; } case kWhatResume: { requestABuffer(); break; } case kWhatShutdown: { onShutdown(); break; } default: TRESPASS(); break; } } } // namespace android Loading
media/libmediaplayerservice/nuplayer/Android.mk +1 −0 Original line number Diff line number Diff line Loading @@ -6,6 +6,7 @@ LOCAL_SRC_FILES:= \ HTTPLiveSource.cpp \ NuPlayer.cpp \ NuPlayerDecoder.cpp \ NuPlayerDecoderPassThrough.cpp \ NuPlayerDriver.cpp \ NuPlayerRenderer.cpp \ NuPlayerStreamListener.cpp \ Loading
media/libmediaplayerservice/nuplayer/NuPlayer.cpp +114 −14 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include "HTTPLiveSource.h" #include "NuPlayerDecoder.h" #include "NuPlayerDecoderPassThrough.h" #include "NuPlayerDriver.h" #include "NuPlayerRenderer.h" #include "NuPlayerSource.h" Loading Loading @@ -143,6 +144,7 @@ NuPlayer::NuPlayer() : mUIDValid(false), mSourceFlags(0), mVideoIsAVC(false), mOffloadAudio(false), mAudioEOS(false), mVideoEOS(false), mScanSourcesPending(false), Loading Loading @@ -500,6 +502,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { ALOGV("kWhatStart"); mVideoIsAVC = false; mOffloadAudio = false; mAudioEOS = false; mVideoEOS = false; mSkipRenderingAudioUntilMediaTimeUs = -1; Loading @@ -517,6 +520,21 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { flags |= Renderer::FLAG_REAL_TIME; } sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); audio_stream_type_t streamType = AUDIO_STREAM_MUSIC; if (mAudioSink != NULL) { streamType = mAudioSink->getAudioStreamType(); } sp<AMessage> videoFormat = mSource->getFormat(false /* audio */); mOffloadAudio = canOffloadStream(audioMeta, (videoFormat != NULL), true /* is_streaming */, streamType); if (mOffloadAudio) { flags |= Renderer::FLAG_OFFLOAD_AUDIO; } mRenderer = new Renderer( mAudioSink, new AMessage(kWhatRendererNotify, id()), Loading Loading @@ -661,7 +679,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { mAudioSink->close(); audio_output_flags_t flags; uint32_t flags; int64_t durationUs; // FIXME: we should handle the case where the video decoder // is created after we receive the format change indication. Loading @@ -682,6 +700,80 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; } if (mOffloadAudio) { audio_format_t audioFormat = AUDIO_FORMAT_PCM_16_BIT; audio_offload_info_t offloadInfo = AUDIO_INFO_INITIALIZER; AString mime; CHECK(format->findString("mime", &mime)); status_t err = mapMimeToAudioFormat(audioFormat, mime.c_str()); if (err != OK) { ALOGE("Couldn't map mime \"%s\" to a valid " "audio_format", mime.c_str()); mOffloadAudio = false; } else { ALOGV("Mime \"%s\" mapped to audio_format 0x%x", mime.c_str(), audioFormat); flags |= AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; offloadInfo.duration_us = -1; format->findInt64( "durationUs", &offloadInfo.duration_us); int avgBitRate = -1; format->findInt32("bit-rate", &avgBitRate); offloadInfo.sample_rate = sampleRate; offloadInfo.channel_mask = channelMask; offloadInfo.format = audioFormat; offloadInfo.stream_type = AUDIO_STREAM_MUSIC; offloadInfo.bit_rate = avgBitRate; offloadInfo.has_video = (mVideoDecoder != NULL); offloadInfo.is_streaming = true; err = mAudioSink->open( sampleRate, numChannels, (audio_channel_mask_t)channelMask, audioFormat, 8 /* bufferCount */, &NuPlayer::Renderer::AudioSinkCallback, mRenderer.get(), (audio_output_flags_t)flags, &offloadInfo); if (err == OK) { // If the playback is offloaded to h/w, we pass // the HAL some metadata information. // We don't want to do this for PCM because it // will be going through the AudioFlinger mixer // before reaching the hardware. sp<MetaData> audioMeta = mSource->getFormatMeta(true /* audio */); sendMetaDataToHal(mAudioSink, audioMeta); err = mAudioSink->start(); } } if (err != OK) { // Clean up, fall back to non offload mode. mAudioSink->close(); mAudioDecoder.clear(); mRenderer->signalDisableOffloadAudio(); mOffloadAudio = false; instantiateDecoder( true /* audio */, &mAudioDecoder); } } if (!mOffloadAudio) { flags &= ~AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD; CHECK_EQ(mAudioSink->open( sampleRate, numChannels, Loading @@ -690,9 +782,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { 8 /* bufferCount */, NULL, NULL, flags), (audio_output_flags_t)flags), (status_t)OK); mAudioSink->start(); } mRenderer->signalAudioSinkChanged(); } else { Loading Loading @@ -968,8 +1061,15 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, id()); *decoder = audio ? new Decoder(notify) : new Decoder(notify, mNativeWindow); if (audio) { if (mOffloadAudio) { *decoder = new DecoderPassThrough(notify); } else { *decoder = new Decoder(notify); } } else { *decoder = new Decoder(notify, mNativeWindow); } (*decoder)->init(); (*decoder)->configure(format); Loading
media/libmediaplayerservice/nuplayer/NuPlayer.h +2 −0 Original line number Diff line number Diff line Loading @@ -76,6 +76,7 @@ public: private: struct Decoder; struct DecoderPassThrough; struct CCDecoder; struct GenericSource; struct HTTPLiveSource; Loading Loading @@ -120,6 +121,7 @@ private: sp<MediaPlayerBase::AudioSink> mAudioSink; sp<Decoder> mVideoDecoder; bool mVideoIsAVC; bool mOffloadAudio; sp<Decoder> mAudioDecoder; sp<CCDecoder> mCCDecoder; sp<Renderer> mRenderer; Loading
media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h +6 −6 Original line number Diff line number Diff line Loading @@ -31,14 +31,14 @@ struct NuPlayer::Decoder : public AHandler { Decoder(const sp<AMessage> ¬ify, const sp<NativeWindowWrapper> &nativeWindow = NULL); void configure(const sp<AMessage> &format); void init(); virtual void configure(const sp<AMessage> &format); virtual void init(); void signalFlush(); void signalResume(); void initiateShutdown(); virtual void signalFlush(); virtual void signalResume(); virtual void initiateShutdown(); bool supportsSeamlessFormatChange(const sp<AMessage> &to) const; virtual bool supportsSeamlessFormatChange(const sp<AMessage> &to) const; enum { kWhatFillThisBuffer = 'flTB', Loading
media/libmediaplayerservice/nuplayer/NuPlayerDecoderPassThrough.cpp 0 → 100644 +237 −0 Original line number Diff line number Diff line /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ //#define LOG_NDEBUG 0 #define LOG_TAG "NuPlayerDecoderPassThrough" #include <utils/Log.h> #include <inttypes.h> #include "NuPlayerDecoderPassThrough.h" #include <media/ICrypto.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> namespace android { static const int kMaxPendingBuffers = 10; NuPlayer::DecoderPassThrough::DecoderPassThrough( const sp<AMessage> ¬ify) : Decoder(notify), mNotify(notify), mBufferGeneration(0), mReachedEOS(true), mPendingBuffers(0), mComponentName("pass through decoder") { mDecoderLooper = new ALooper; mDecoderLooper->setName("NuPlayerDecoderPassThrough"); mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO); } NuPlayer::DecoderPassThrough::~DecoderPassThrough() { } void NuPlayer::DecoderPassThrough::configure(const sp<AMessage> &format) { sp<AMessage> msg = new AMessage(kWhatConfigure, id()); msg->setMessage("format", format); msg->post(); } void NuPlayer::DecoderPassThrough::init() { mDecoderLooper->registerHandler(this); } void NuPlayer::DecoderPassThrough::signalFlush() { (new AMessage(kWhatFlush, id()))->post(); } void NuPlayer::DecoderPassThrough::signalResume() { (new AMessage(kWhatResume, id()))->post(); } void NuPlayer::DecoderPassThrough::initiateShutdown() { (new AMessage(kWhatShutdown, id()))->post(); } bool NuPlayer::DecoderPassThrough::supportsSeamlessFormatChange( const sp<AMessage> & /* targetFormat */) const { return true; } void NuPlayer::DecoderPassThrough::onConfigure(const sp<AMessage> &format) { ALOGV("[%s] onConfigure", mComponentName.c_str()); mPendingBuffers = 0; mReachedEOS = false; ++mBufferGeneration; requestABuffer(); sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatOutputFormatChanged); notify->setMessage("format", format); notify->post(); } bool NuPlayer::DecoderPassThrough::isStaleReply(const sp<AMessage> &msg) { int32_t generation; CHECK(msg->findInt32("generation", &generation)); return generation != mBufferGeneration; } void NuPlayer::DecoderPassThrough::requestABuffer() { if (mPendingBuffers >= kMaxPendingBuffers || mReachedEOS) { ALOGV("[%s] mReachedEOS=%d, max pending buffers(%d:%d)", mComponentName.c_str(), (mReachedEOS ? 1 : 0), mPendingBuffers, kMaxPendingBuffers); return; } sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id()); reply->setInt32("generation", mBufferGeneration); sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatFillThisBuffer); notify->setMessage("reply", reply); notify->post(); mPendingBuffers++; sp<AMessage> message = new AMessage(kWhatRequestABuffer, id()); message->setInt32("generation", mBufferGeneration); message->post(); return; } void android::NuPlayer::DecoderPassThrough::onInputBufferFilled( const sp<AMessage> &msg) { if (mReachedEOS) { return; } sp<ABuffer> buffer; msg->findBuffer("buffer", &buffer); if (buffer == NULL) { mReachedEOS = true; sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatEOS); notify->setInt32("err", ERROR_END_OF_STREAM); notify->post(); return; } sp<AMessage> reply = new AMessage(kWhatBufferConsumed, id()); reply->setInt32("generation", mBufferGeneration); sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatDrainThisBuffer); notify->setBuffer("buffer", buffer); notify->setMessage("reply", reply); notify->post(); } void NuPlayer::DecoderPassThrough::onBufferConsumed() { mPendingBuffers--; sp<AMessage> message = new AMessage(kWhatRequestABuffer, id()); message->setInt32("generation", mBufferGeneration); message->post(); } void NuPlayer::DecoderPassThrough::onFlush() { ++mBufferGeneration; sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatFlushCompleted); notify->post(); mPendingBuffers = 0; mReachedEOS = false; } void NuPlayer::DecoderPassThrough::onShutdown() { ++mBufferGeneration; sp<AMessage> notify = mNotify->dup(); notify->setInt32("what", kWhatShutdownCompleted); notify->post(); mReachedEOS = true; } void NuPlayer::DecoderPassThrough::onMessageReceived(const sp<AMessage> &msg) { ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str()); switch (msg->what()) { case kWhatConfigure: { sp<AMessage> format; CHECK(msg->findMessage("format", &format)); onConfigure(format); break; } case kWhatRequestABuffer: { if (!isStaleReply(msg)) { requestABuffer(); } break; } case kWhatInputBufferFilled: { if (!isStaleReply(msg)) { onInputBufferFilled(msg); } break; } case kWhatBufferConsumed: { if (!isStaleReply(msg)) { onBufferConsumed(); } break; } case kWhatFlush: { onFlush(); break; } case kWhatResume: { requestABuffer(); break; } case kWhatShutdown: { onShutdown(); break; } default: TRESPASS(); break; } } } // namespace android