Loading services/audioflinger/AudioFlinger.cpp +99 −16 Original line number Original line Diff line number Diff line Loading @@ -1392,12 +1392,13 @@ status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String // Thread virtuals // Thread virtuals status_t AudioFlinger::PlaybackThread::readyToRun() status_t AudioFlinger::PlaybackThread::readyToRun() { { if (mSampleRate == 0) { status_t status = initCheck(); if (status == NO_ERROR) { LOGI("AudioFlinger's thread %p ready to run", this); } else { LOGE("No working audio driver found."); LOGE("No working audio driver found."); return NO_INIT; } } LOGI("AudioFlinger's thread %p ready to run", this); return status; return NO_ERROR; } } void AudioFlinger::PlaybackThread::onFirstRef() void AudioFlinger::PlaybackThread::onFirstRef() Loading Loading @@ -1491,10 +1492,10 @@ Exit: uint32_t AudioFlinger::PlaybackThread::latency() const uint32_t AudioFlinger::PlaybackThread::latency() const { { if (mOutput) { Mutex::Autolock _l(mLock); if (initCheck() == NO_ERROR) { return mOutput->stream->get_latency(mOutput->stream); return mOutput->stream->get_latency(mOutput->stream); } } else { else { return 0; return 0; } } } } Loading Loading @@ -1595,16 +1596,21 @@ void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track) String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) { { String8 out_s8; String8 out_s8 = String8(""); char *s; char *s; Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { return out_s8; } s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string()); s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string()); out_s8 = String8(s); out_s8 = String8(s); free(s); free(s); return out_s8; return out_s8; } } // destroyTrack_l() must be called with AudioFlinger::mLock held // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { AudioSystem::OutputDescriptor desc; AudioSystem::OutputDescriptor desc; void *param2 = 0; void *param2 = 0; Loading Loading @@ -1663,6 +1669,7 @@ status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, ui if (halFrames == 0 || dspFrames == 0) { if (halFrames == 0 || dspFrames == 0) { return BAD_VALUE; return BAD_VALUE; } } Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { if (initCheck() != NO_ERROR) { return INVALID_OPERATION; return INVALID_OPERATION; } } Loading Loading @@ -1709,6 +1716,29 @@ uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId) } } AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() { Mutex::Autolock _l(mLock); return mOutput; } AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput() { Mutex::Autolock _l(mLock); AudioStreamOut *output = mOutput; mOutput = NULL; return output; } // this method must always be called either with ThreadBase mLock held or inside the thread loop audio_stream_t* AudioFlinger::PlaybackThread::stream() { if (mOutput == NULL) { return NULL; } return &mOutput->stream->common; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) Loading Loading @@ -4083,6 +4113,13 @@ void AudioFlinger::RecordThread::onFirstRef() run(mName, PRIORITY_URGENT_AUDIO); run(mName, PRIORITY_URGENT_AUDIO); } } status_t AudioFlinger::RecordThread::readyToRun() { status_t status = initCheck(); LOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this); return status; } bool AudioFlinger::RecordThread::threadLoop() bool AudioFlinger::RecordThread::threadLoop() { { AudioBufferProvider::Buffer buffer; AudioBufferProvider::Buffer buffer; Loading Loading @@ -4573,7 +4610,12 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() String8 AudioFlinger::RecordThread::getParameters(const String8& keys) String8 AudioFlinger::RecordThread::getParameters(const String8& keys) { { char *s; char *s; String8 out_s8; String8 out_s8 = String8(); Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { return out_s8; } s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string()); s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string()); out_s8 = String8(s); out_s8 = String8(s); Loading Loading @@ -4645,6 +4687,11 @@ void AudioFlinger::RecordThread::readInputParameters() unsigned int AudioFlinger::RecordThread::getInputFramesLost() unsigned int AudioFlinger::RecordThread::getInputFramesLost() { { Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { return 0; } return mInput->stream->get_input_frames_lost(mInput->stream); return mInput->stream->get_input_frames_lost(mInput->stream); } } Loading @@ -4669,6 +4716,30 @@ AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track() return mTrack; return mTrack; } } AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() { Mutex::Autolock _l(mLock); return mInput; } AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput() { Mutex::Autolock _l(mLock); AudioStreamIn *input = mInput; mInput = NULL; return input; } // this method must always be called either with ThreadBase mLock held or inside the thread loop audio_stream_t* AudioFlinger::RecordThread::stream() { if (mInput == NULL) { return NULL; } return &mInput->stream->common; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- int AudioFlinger::openOutput(uint32_t *pDevices, int AudioFlinger::openOutput(uint32_t *pDevices, Loading Loading @@ -4792,7 +4863,8 @@ status_t AudioFlinger::closeOutput(int output) thread->exit(); thread->exit(); if (thread->type() != ThreadBase::DUPLICATING) { if (thread->type() != ThreadBase::DUPLICATING) { AudioStreamOut *out = thread->getOutput(); AudioStreamOut *out = thread->clearOutput(); // from now on thread->mOutput is NULL out->hwDev->close_output_stream(out->hwDev, out->stream); out->hwDev->close_output_stream(out->hwDev, out->stream); delete out; delete out; } } Loading Loading @@ -4932,7 +5004,8 @@ status_t AudioFlinger::closeInput(int input) } } thread->exit(); thread->exit(); AudioStreamIn *in = thread->getInput(); AudioStreamIn *in = thread->clearInput(); // from now on thread->mInput is NULL in->hwDev->close_input_stream(in->hwDev, in->stream); in->hwDev->close_input_stream(in->hwDev, in->stream); delete in; delete in; Loading Loading @@ -5010,7 +5083,8 @@ AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() { { for (size_t i = 0; i < mPlaybackThreads.size(); i++) { for (size_t i = 0; i < mPlaybackThreads.size(); i++) { PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); if (thread->getOutput()->hwDev == mPrimaryHardwareDev) { AudioStreamOut *output = thread->getOutput(); if (output != NULL && output->hwDev == mPrimaryHardwareDev) { return thread; return thread; } } } } Loading Loading @@ -5789,7 +5863,10 @@ AudioFlinger::EffectModule::~EffectModule() (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) { (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) { sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface); audio_stream_t *stream = thread->stream(); if (stream != NULL) { stream->remove_audio_effect(stream, mEffectInterface); } } } } } // release effect engine // release effect engine Loading Loading @@ -6104,7 +6181,10 @@ status_t AudioFlinger::EffectModule::start_l() (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { thread->stream()->add_audio_effect(thread->stream(), mEffectInterface); audio_stream_t *stream = thread->stream(); if (stream != NULL) { stream->add_audio_effect(stream, mEffectInterface); } } } } } return status; return status; Loading Loading @@ -6137,7 +6217,10 @@ status_t AudioFlinger::EffectModule::stop_l() (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface); audio_stream_t *stream = thread->stream(); if (stream != NULL) { stream->remove_audio_effect(stream, mEffectInterface); } } } } } return status; return status; Loading services/audioflinger/AudioFlinger.h +7 −5 Original line number Original line Diff line number Diff line Loading @@ -724,8 +724,9 @@ private: int sessionId, int sessionId, status_t *status); status_t *status); AudioStreamOut* getOutput() { return mOutput; } AudioStreamOut* getOutput(); virtual audio_stream_t* stream() { return &mOutput->stream->common; } AudioStreamOut* clearOutput(); virtual audio_stream_t* stream(); void suspend() { mSuspended++; } void suspend() { mSuspended++; } void restore() { if (mSuspended) mSuspended--; } void restore() { if (mSuspended) mSuspended--; } Loading Loading @@ -967,7 +968,7 @@ private: ~RecordThread(); ~RecordThread(); virtual bool threadLoop(); virtual bool threadLoop(); virtual status_t readyToRun() { return NO_ERROR; } virtual status_t readyToRun(); virtual void onFirstRef(); virtual void onFirstRef(); virtual status_t initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; } virtual status_t initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; } Loading @@ -984,8 +985,9 @@ private: status_t start(RecordTrack* recordTrack); status_t start(RecordTrack* recordTrack); void stop(RecordTrack* recordTrack); void stop(RecordTrack* recordTrack); status_t dump(int fd, const Vector<String16>& args); status_t dump(int fd, const Vector<String16>& args); AudioStreamIn* getInput() { return mInput; } AudioStreamIn* getInput(); virtual audio_stream_t* stream() { return &mInput->stream->common; } AudioStreamIn* clearInput(); virtual audio_stream_t* stream(); virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); Loading Loading
services/audioflinger/AudioFlinger.cpp +99 −16 Original line number Original line Diff line number Diff line Loading @@ -1392,12 +1392,13 @@ status_t AudioFlinger::PlaybackThread::dumpInternals(int fd, const Vector<String // Thread virtuals // Thread virtuals status_t AudioFlinger::PlaybackThread::readyToRun() status_t AudioFlinger::PlaybackThread::readyToRun() { { if (mSampleRate == 0) { status_t status = initCheck(); if (status == NO_ERROR) { LOGI("AudioFlinger's thread %p ready to run", this); } else { LOGE("No working audio driver found."); LOGE("No working audio driver found."); return NO_INIT; } } LOGI("AudioFlinger's thread %p ready to run", this); return status; return NO_ERROR; } } void AudioFlinger::PlaybackThread::onFirstRef() void AudioFlinger::PlaybackThread::onFirstRef() Loading Loading @@ -1491,10 +1492,10 @@ Exit: uint32_t AudioFlinger::PlaybackThread::latency() const uint32_t AudioFlinger::PlaybackThread::latency() const { { if (mOutput) { Mutex::Autolock _l(mLock); if (initCheck() == NO_ERROR) { return mOutput->stream->get_latency(mOutput->stream); return mOutput->stream->get_latency(mOutput->stream); } } else { else { return 0; return 0; } } } } Loading Loading @@ -1595,16 +1596,21 @@ void AudioFlinger::PlaybackThread::removeTrack_l(const sp<Track>& track) String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) String8 AudioFlinger::PlaybackThread::getParameters(const String8& keys) { { String8 out_s8; String8 out_s8 = String8(""); char *s; char *s; Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { return out_s8; } s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string()); s = mOutput->stream->common.get_parameters(&mOutput->stream->common, keys.string()); out_s8 = String8(s); out_s8 = String8(s); free(s); free(s); return out_s8; return out_s8; } } // destroyTrack_l() must be called with AudioFlinger::mLock held // audioConfigChanged_l() must be called with AudioFlinger::mLock held void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { void AudioFlinger::PlaybackThread::audioConfigChanged_l(int event, int param) { AudioSystem::OutputDescriptor desc; AudioSystem::OutputDescriptor desc; void *param2 = 0; void *param2 = 0; Loading Loading @@ -1663,6 +1669,7 @@ status_t AudioFlinger::PlaybackThread::getRenderPosition(uint32_t *halFrames, ui if (halFrames == 0 || dspFrames == 0) { if (halFrames == 0 || dspFrames == 0) { return BAD_VALUE; return BAD_VALUE; } } Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { if (initCheck() != NO_ERROR) { return INVALID_OPERATION; return INVALID_OPERATION; } } Loading Loading @@ -1709,6 +1716,29 @@ uint32_t AudioFlinger::PlaybackThread::getStrategyForSession_l(int sessionId) } } AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::getOutput() { Mutex::Autolock _l(mLock); return mOutput; } AudioFlinger::AudioStreamOut* AudioFlinger::PlaybackThread::clearOutput() { Mutex::Autolock _l(mLock); AudioStreamOut *output = mOutput; mOutput = NULL; return output; } // this method must always be called either with ThreadBase mLock held or inside the thread loop audio_stream_t* AudioFlinger::PlaybackThread::stream() { if (mOutput == NULL) { return NULL; } return &mOutput->stream->common; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) AudioFlinger::MixerThread::MixerThread(const sp<AudioFlinger>& audioFlinger, AudioStreamOut* output, int id, uint32_t device) Loading Loading @@ -4083,6 +4113,13 @@ void AudioFlinger::RecordThread::onFirstRef() run(mName, PRIORITY_URGENT_AUDIO); run(mName, PRIORITY_URGENT_AUDIO); } } status_t AudioFlinger::RecordThread::readyToRun() { status_t status = initCheck(); LOGW_IF(status != NO_ERROR,"RecordThread %p could not initialize", this); return status; } bool AudioFlinger::RecordThread::threadLoop() bool AudioFlinger::RecordThread::threadLoop() { { AudioBufferProvider::Buffer buffer; AudioBufferProvider::Buffer buffer; Loading Loading @@ -4573,7 +4610,12 @@ bool AudioFlinger::RecordThread::checkForNewParameters_l() String8 AudioFlinger::RecordThread::getParameters(const String8& keys) String8 AudioFlinger::RecordThread::getParameters(const String8& keys) { { char *s; char *s; String8 out_s8; String8 out_s8 = String8(); Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { return out_s8; } s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string()); s = mInput->stream->common.get_parameters(&mInput->stream->common, keys.string()); out_s8 = String8(s); out_s8 = String8(s); Loading Loading @@ -4645,6 +4687,11 @@ void AudioFlinger::RecordThread::readInputParameters() unsigned int AudioFlinger::RecordThread::getInputFramesLost() unsigned int AudioFlinger::RecordThread::getInputFramesLost() { { Mutex::Autolock _l(mLock); if (initCheck() != NO_ERROR) { return 0; } return mInput->stream->get_input_frames_lost(mInput->stream); return mInput->stream->get_input_frames_lost(mInput->stream); } } Loading @@ -4669,6 +4716,30 @@ AudioFlinger::RecordThread::RecordTrack* AudioFlinger::RecordThread::track() return mTrack; return mTrack; } } AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::getInput() { Mutex::Autolock _l(mLock); return mInput; } AudioFlinger::AudioStreamIn* AudioFlinger::RecordThread::clearInput() { Mutex::Autolock _l(mLock); AudioStreamIn *input = mInput; mInput = NULL; return input; } // this method must always be called either with ThreadBase mLock held or inside the thread loop audio_stream_t* AudioFlinger::RecordThread::stream() { if (mInput == NULL) { return NULL; } return &mInput->stream->common; } // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- int AudioFlinger::openOutput(uint32_t *pDevices, int AudioFlinger::openOutput(uint32_t *pDevices, Loading Loading @@ -4792,7 +4863,8 @@ status_t AudioFlinger::closeOutput(int output) thread->exit(); thread->exit(); if (thread->type() != ThreadBase::DUPLICATING) { if (thread->type() != ThreadBase::DUPLICATING) { AudioStreamOut *out = thread->getOutput(); AudioStreamOut *out = thread->clearOutput(); // from now on thread->mOutput is NULL out->hwDev->close_output_stream(out->hwDev, out->stream); out->hwDev->close_output_stream(out->hwDev, out->stream); delete out; delete out; } } Loading Loading @@ -4932,7 +5004,8 @@ status_t AudioFlinger::closeInput(int input) } } thread->exit(); thread->exit(); AudioStreamIn *in = thread->getInput(); AudioStreamIn *in = thread->clearInput(); // from now on thread->mInput is NULL in->hwDev->close_input_stream(in->hwDev, in->stream); in->hwDev->close_input_stream(in->hwDev, in->stream); delete in; delete in; Loading Loading @@ -5010,7 +5083,8 @@ AudioFlinger::PlaybackThread *AudioFlinger::primaryPlaybackThread_l() { { for (size_t i = 0; i < mPlaybackThreads.size(); i++) { for (size_t i = 0; i < mPlaybackThreads.size(); i++) { PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); PlaybackThread *thread = mPlaybackThreads.valueAt(i).get(); if (thread->getOutput()->hwDev == mPrimaryHardwareDev) { AudioStreamOut *output = thread->getOutput(); if (output != NULL && output->hwDev == mPrimaryHardwareDev) { return thread; return thread; } } } } Loading Loading @@ -5789,7 +5863,10 @@ AudioFlinger::EffectModule::~EffectModule() (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) { (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC) { sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface); audio_stream_t *stream = thread->stream(); if (stream != NULL) { stream->remove_audio_effect(stream, mEffectInterface); } } } } } // release effect engine // release effect engine Loading Loading @@ -6104,7 +6181,10 @@ status_t AudioFlinger::EffectModule::start_l() (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { thread->stream()->add_audio_effect(thread->stream(), mEffectInterface); audio_stream_t *stream = thread->stream(); if (stream != NULL) { stream->add_audio_effect(stream, mEffectInterface); } } } } } return status; return status; Loading Loading @@ -6137,7 +6217,10 @@ status_t AudioFlinger::EffectModule::stop_l() (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { (mDescriptor.flags & EFFECT_FLAG_TYPE_MASK) == EFFECT_FLAG_TYPE_POST_PROC)) { sp<ThreadBase> thread = mThread.promote(); sp<ThreadBase> thread = mThread.promote(); if (thread != 0) { if (thread != 0) { thread->stream()->remove_audio_effect(thread->stream(), mEffectInterface); audio_stream_t *stream = thread->stream(); if (stream != NULL) { stream->remove_audio_effect(stream, mEffectInterface); } } } } } return status; return status; Loading
services/audioflinger/AudioFlinger.h +7 −5 Original line number Original line Diff line number Diff line Loading @@ -724,8 +724,9 @@ private: int sessionId, int sessionId, status_t *status); status_t *status); AudioStreamOut* getOutput() { return mOutput; } AudioStreamOut* getOutput(); virtual audio_stream_t* stream() { return &mOutput->stream->common; } AudioStreamOut* clearOutput(); virtual audio_stream_t* stream(); void suspend() { mSuspended++; } void suspend() { mSuspended++; } void restore() { if (mSuspended) mSuspended--; } void restore() { if (mSuspended) mSuspended--; } Loading Loading @@ -967,7 +968,7 @@ private: ~RecordThread(); ~RecordThread(); virtual bool threadLoop(); virtual bool threadLoop(); virtual status_t readyToRun() { return NO_ERROR; } virtual status_t readyToRun(); virtual void onFirstRef(); virtual void onFirstRef(); virtual status_t initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; } virtual status_t initCheck() const { return (mInput == 0) ? NO_INIT : NO_ERROR; } Loading @@ -984,8 +985,9 @@ private: status_t start(RecordTrack* recordTrack); status_t start(RecordTrack* recordTrack); void stop(RecordTrack* recordTrack); void stop(RecordTrack* recordTrack); status_t dump(int fd, const Vector<String16>& args); status_t dump(int fd, const Vector<String16>& args); AudioStreamIn* getInput() { return mInput; } AudioStreamIn* getInput(); virtual audio_stream_t* stream() { return &mInput->stream->common; } AudioStreamIn* clearInput(); virtual audio_stream_t* stream(); virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); virtual status_t getNextBuffer(AudioBufferProvider::Buffer* buffer); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); virtual void releaseBuffer(AudioBufferProvider::Buffer* buffer); Loading