Loading media/libaudioclient/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -146,6 +146,7 @@ cc_library { "spatializer-aidl-cpp", "spatializer-aidl-cpp", "framework-permission-aidl-cpp", "framework-permission-aidl-cpp", "libbinder", "libbinder", "libmediametrics", ], ], include_dirs: [ include_dirs: [ Loading media/libmediaplayerservice/Android.bp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ cc_library { header_libs: [ header_libs: [ "media_plugin_headers", "media_plugin_headers", "libmediautils_headers", ], ], static_libs: [ static_libs: [ Loading @@ -85,6 +86,10 @@ cc_library { "framework-permission-aidl-cpp", "framework-permission-aidl-cpp", ], ], export_header_lib_headers: [ "libmediautils_headers", ], include_dirs: [ include_dirs: [ "frameworks/av/media/libstagefright/rtsp", "frameworks/av/media/libstagefright/rtsp", "frameworks/av/media/libstagefright/webm", "frameworks/av/media/libstagefright/webm", Loading media/libmediaplayerservice/MediaPlayerService.cpp +68 −79 Original line number Original line Diff line number Diff line Loading @@ -1831,7 +1831,6 @@ MediaPlayerService::AudioOutput::~AudioOutput() { { close(); close(); free(mAttributes); free(mAttributes); delete mCallbackData; } } //static //static Loading Loading @@ -2052,8 +2051,7 @@ void MediaPlayerService::AudioOutput::deleteRecycledTrack_l() mRecycledTrack.clear(); mRecycledTrack.clear(); close_l(); close_l(); delete mCallbackData; mCallbackData.clear(); mCallbackData = NULL; } } } } Loading Loading @@ -2174,7 +2172,7 @@ status_t MediaPlayerService::AudioOutput::open( } } sp<AudioTrack> t; sp<AudioTrack> t; CallbackData *newcbd = NULL; sp<CallbackData> newcbd; // We don't attempt to create a new track if we are recycling an // We don't attempt to create a new track if we are recycling an // offloaded track. But, if we are recycling a non-offloaded or we // offloaded track. But, if we are recycling a non-offloaded or we Loading @@ -2184,8 +2182,8 @@ status_t MediaPlayerService::AudioOutput::open( if (!(reuse && bothOffloaded)) { if (!(reuse && bothOffloaded)) { ALOGV("creating new AudioTrack"); ALOGV("creating new AudioTrack"); if (mCallback != NULL) { if (mCallback != nullptr) { newcbd = new CallbackData(this); newcbd = sp<CallbackData>::make(wp<AudioOutput>::fromExisting(this)); t = new AudioTrack( t = new AudioTrack( mStreamType, mStreamType, sampleRate, sampleRate, Loading @@ -2193,7 +2191,6 @@ status_t MediaPlayerService::AudioOutput::open( channelMask, channelMask, frameCount, frameCount, flags, flags, CallbackWrapper, newcbd, newcbd, 0, // notification frames 0, // notification frames mSessionId, mSessionId, Loading Loading @@ -2237,8 +2234,7 @@ status_t MediaPlayerService::AudioOutput::open( t->setCallerName("media"); t->setCallerName("media"); if ((t == 0) || (t->initCheck() != NO_ERROR)) { if ((t == 0) || (t->initCheck() != NO_ERROR)) { ALOGE("Unable to create audio track"); ALOGE("Unable to create audio track"); delete newcbd; // t, newcbd goes out of scope, so reference count drops to zero // t goes out of scope, so reference count drops to zero return NO_INIT; return NO_INIT; } else { } else { // successful AudioTrack initialization implies a legacy stream type was generated // successful AudioTrack initialization implies a legacy stream type was generated Loading Loading @@ -2272,7 +2268,6 @@ status_t MediaPlayerService::AudioOutput::open( if (mCallbackData != NULL) { if (mCallbackData != NULL) { mCallbackData->setOutput(this); mCallbackData->setOutput(this); } } delete newcbd; return updateTrack(); return updateTrack(); } } } } Loading Loading @@ -2378,7 +2373,7 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() { if (mCallbackData != NULL) { if (mCallbackData != NULL) { // two alternative approaches // two alternative approaches #if 1 #if 1 CallbackData *callbackData = mCallbackData; sp<CallbackData> callbackData = mCallbackData; mLock.unlock(); mLock.unlock(); // proper acquisition sequence // proper acquisition sequence callbackData->lock(); callbackData->lock(); Loading Loading @@ -2415,9 +2410,8 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() { // for example, the next player could be prepared and seeked. // for example, the next player could be prepared and seeked. // // // Presuming it isn't advisable to force the track over. // Presuming it isn't advisable to force the track over. if (mNextOutput->mTrack == NULL) { if (mNextOutput->mTrack == nullptr) { ALOGD("Recycling track for gapless playback"); ALOGD("Recycling track for gapless playback"); delete mNextOutput->mCallbackData; mNextOutput->mCallbackData = mCallbackData; mNextOutput->mCallbackData = mCallbackData; mNextOutput->mRecycledTrack = mTrack; mNextOutput->mRecycledTrack = mTrack; mNextOutput->mSampleRateHz = mSampleRateHz; mNextOutput->mSampleRateHz = mSampleRateHz; Loading @@ -2425,11 +2419,11 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() { mNextOutput->mFlags = mFlags; mNextOutput->mFlags = mFlags; mNextOutput->mFrameSize = mFrameSize; mNextOutput->mFrameSize = mFrameSize; close_l(); close_l(); mCallbackData = NULL; // destruction handled by mNextOutput mCallbackData.clear(); } else { } else { ALOGW("Ignoring gapless playback because next player has already started"); ALOGW("Ignoring gapless playback because next player has already started"); // remove track in case resource needed for future players. // remove track in case resource needed for future players. if (mCallbackData != NULL) { if (mCallbackData != nullptr) { mCallbackData->endTrackSwitch(); // release lock for callbacks before close. mCallbackData->endTrackSwitch(); // release lock for callbacks before close. } } close_l(); close_l(); Loading Loading @@ -2656,29 +2650,16 @@ sp<VolumeShaper::State> MediaPlayerService::AudioOutput::getVolumeShaperState(in } } } } // static size_t MediaPlayerService::AudioOutput::CallbackData::onMoreData(const AudioTrack::Buffer& buffer) { void MediaPlayerService::AudioOutput::CallbackWrapper( ALOGD("data callback"); int event, void *cookie, void *info) { lock(); //ALOGV("callbackwrapper"); sp<AudioOutput> me = getOutput(); CallbackData *data = (CallbackData*)cookie; if (me == nullptr) { // lock to ensure we aren't caught in the middle of a track switch. unlock(); data->lock(); return 0; AudioOutput *me = data->getOutput(); AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; if (me == NULL) { // no output set, likely because the track was scheduled to be reused // by another player, but the format turned out to be incompatible. data->unlock(); if (buffer != NULL) { buffer->size = 0; } return; } } switch(event) { case AudioTrack::EVENT_MORE_DATA: { size_t actualSize = (*me->mCallback)( size_t actualSize = (*me->mCallback)( me, buffer->raw, buffer->size, me->mCallbackCookie, me.get(), buffer.raw, buffer.size, me->mCallbackCookie, CB_EVENT_FILL_BUFFER); CB_EVENT_FILL_BUFFER); // Log when no data is returned from the callback. // Log when no data is returned from the callback. Loading @@ -2691,24 +2672,38 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( // nevertheless for power reasons, we don't want to see too many of these. // nevertheless for power reasons, we don't want to see too many of these. ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned"); ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned"); unlock(); return actualSize; } buffer->size = actualSize; void MediaPlayerService::AudioOutput::CallbackData::onStreamEnd() { } break; lock(); sp<AudioOutput> me = getOutput(); case AudioTrack::EVENT_STREAM_END: if (me == nullptr) { // currently only occurs for offloaded callbacks unlock(); return; } ALOGV("callbackwrapper: deliver EVENT_STREAM_END"); ALOGV("callbackwrapper: deliver EVENT_STREAM_END"); (*me->mCallback)(me, NULL /* buffer */, 0 /* size */, (*me->mCallback)(me.get(), NULL /* buffer */, 0 /* size */, me->mCallbackCookie, CB_EVENT_STREAM_END); me->mCallbackCookie, CB_EVENT_STREAM_END); break; unlock(); } case AudioTrack::EVENT_NEW_IAUDIOTRACK : void MediaPlayerService::AudioOutput::CallbackData::onNewIAudioTrack() { lock(); sp<AudioOutput> me = getOutput(); if (me == nullptr) { unlock(); return; } ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN"); ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN"); (*me->mCallback)(me, NULL /* buffer */, 0 /* size */, (*me->mCallback)(me.get(), NULL /* buffer */, 0 /* size */, me->mCallbackCookie, CB_EVENT_TEAR_DOWN); me->mCallbackCookie, CB_EVENT_TEAR_DOWN); break; unlock(); } case AudioTrack::EVENT_UNDERRUN: void MediaPlayerService::AudioOutput::CallbackData::onUnderrun() { // This occurs when there is no data available, typically // This occurs when there is no data available, typically // when there is a failure to supply data to the AudioTrack. It can also // when there is a failure to supply data to the AudioTrack. It can also // occur in non-offloaded mode when the audio device comes out of standby. // occur in non-offloaded mode when the audio device comes out of standby. Loading @@ -2719,13 +2714,7 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( // The underrun event is sent once per track underrun; the condition is reset // The underrun event is sent once per track underrun; the condition is reset // when more data is sent to the AudioTrack. // when more data is sent to the AudioTrack. ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)"); ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)"); break; default: ALOGE("received unknown event type: %d inside CallbackWrapper !", event); } data->unlock(); } } audio_session_t MediaPlayerService::AudioOutput::getSessionId() const audio_session_t MediaPlayerService::AudioOutput::getSessionId() const Loading media/libmediaplayerservice/MediaPlayerService.h +13 −7 Original line number Original line Diff line number Diff line Loading @@ -30,9 +30,11 @@ #include <media/AidlConversion.h> #include <media/AidlConversion.h> #include <media/AudioResamplerPublic.h> #include <media/AudioResamplerPublic.h> #include <media/AudioSystem.h> #include <media/AudioSystem.h> #include <media/AudioTrack.h> #include <media/MediaPlayerInterface.h> #include <media/MediaPlayerInterface.h> #include <media/Metadata.h> #include <media/Metadata.h> #include <media/stagefright/foundation/ABase.h> #include <media/stagefright/foundation/ABase.h> #include <mediautils/Synchronization.h> #include <android/content/AttributionSourceState.h> #include <android/content/AttributionSourceState.h> #include <system/audio.h> #include <system/audio.h> Loading @@ -41,7 +43,6 @@ namespace android { using content::AttributionSourceState; using content::AttributionSourceState; class AudioTrack; struct AVSyncSettings; struct AVSyncSettings; class DeathNotifier; class DeathNotifier; class IDataSource; class IDataSource; Loading Loading @@ -161,7 +162,7 @@ class MediaPlayerService : public BnMediaPlayerService sp<AudioOutput> mNextOutput; sp<AudioOutput> mNextOutput; AudioCallback mCallback; AudioCallback mCallback; void * mCallbackCookie; void * mCallbackCookie; CallbackData * mCallbackData; sp<CallbackData> mCallbackData; audio_stream_type_t mStreamType; audio_stream_type_t mStreamType; audio_attributes_t * mAttributes; audio_attributes_t * mAttributes; float mLeftVolume; float mLeftVolume; Loading Loading @@ -189,15 +190,15 @@ class MediaPlayerService : public BnMediaPlayerService // CallbackData is what is passed to the AudioTrack as the "user" data. // CallbackData is what is passed to the AudioTrack as the "user" data. // We need to be able to target this to a different Output on the fly, // We need to be able to target this to a different Output on the fly, // so we can't use the Output itself for this. // so we can't use the Output itself for this. class CallbackData { class CallbackData : public AudioTrack::IAudioTrackCallback { friend AudioOutput; friend AudioOutput; public: public: explicit CallbackData(AudioOutput *cookie) { explicit CallbackData(const wp<AudioOutput>& cookie) { mData = cookie; mData = cookie; mSwitching = false; mSwitching = false; } } AudioOutput * getOutput() const { return mData; } sp<AudioOutput> getOutput() const { return mData.load().promote(); } void setOutput(AudioOutput* newcookie) { mData = newcookie; } void setOutput(const wp<AudioOutput>& newcookie) { mData.store(newcookie); } // lock/unlock are used by the callback before accessing the payload of this object // lock/unlock are used by the callback before accessing the payload of this object void lock() const { mLock.lock(); } void lock() const { mLock.lock(); } void unlock() const { mLock.unlock(); } void unlock() const { mLock.unlock(); } Loading @@ -220,8 +221,13 @@ class MediaPlayerService : public BnMediaPlayerService } } mSwitching = false; mSwitching = false; } } protected: size_t onMoreData(const AudioTrack::Buffer& buffer) override; void onUnderrun() override; void onStreamEnd() override; void onNewIAudioTrack() override; private: private: AudioOutput * mData; mediautils::atomic_wp<AudioOutput> mData; mutable Mutex mLock; // a recursive mutex might make this unnecessary. mutable Mutex mLock; // a recursive mutex might make this unnecessary. bool mSwitching; bool mSwitching; DISALLOW_EVIL_CONSTRUCTORS(CallbackData); DISALLOW_EVIL_CONSTRUCTORS(CallbackData); Loading Loading
media/libaudioclient/Android.bp +1 −0 Original line number Original line Diff line number Diff line Loading @@ -146,6 +146,7 @@ cc_library { "spatializer-aidl-cpp", "spatializer-aidl-cpp", "framework-permission-aidl-cpp", "framework-permission-aidl-cpp", "libbinder", "libbinder", "libmediametrics", ], ], include_dirs: [ include_dirs: [ Loading
media/libmediaplayerservice/Android.bp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -70,6 +70,7 @@ cc_library { header_libs: [ header_libs: [ "media_plugin_headers", "media_plugin_headers", "libmediautils_headers", ], ], static_libs: [ static_libs: [ Loading @@ -85,6 +86,10 @@ cc_library { "framework-permission-aidl-cpp", "framework-permission-aidl-cpp", ], ], export_header_lib_headers: [ "libmediautils_headers", ], include_dirs: [ include_dirs: [ "frameworks/av/media/libstagefright/rtsp", "frameworks/av/media/libstagefright/rtsp", "frameworks/av/media/libstagefright/webm", "frameworks/av/media/libstagefright/webm", Loading
media/libmediaplayerservice/MediaPlayerService.cpp +68 −79 Original line number Original line Diff line number Diff line Loading @@ -1831,7 +1831,6 @@ MediaPlayerService::AudioOutput::~AudioOutput() { { close(); close(); free(mAttributes); free(mAttributes); delete mCallbackData; } } //static //static Loading Loading @@ -2052,8 +2051,7 @@ void MediaPlayerService::AudioOutput::deleteRecycledTrack_l() mRecycledTrack.clear(); mRecycledTrack.clear(); close_l(); close_l(); delete mCallbackData; mCallbackData.clear(); mCallbackData = NULL; } } } } Loading Loading @@ -2174,7 +2172,7 @@ status_t MediaPlayerService::AudioOutput::open( } } sp<AudioTrack> t; sp<AudioTrack> t; CallbackData *newcbd = NULL; sp<CallbackData> newcbd; // We don't attempt to create a new track if we are recycling an // We don't attempt to create a new track if we are recycling an // offloaded track. But, if we are recycling a non-offloaded or we // offloaded track. But, if we are recycling a non-offloaded or we Loading @@ -2184,8 +2182,8 @@ status_t MediaPlayerService::AudioOutput::open( if (!(reuse && bothOffloaded)) { if (!(reuse && bothOffloaded)) { ALOGV("creating new AudioTrack"); ALOGV("creating new AudioTrack"); if (mCallback != NULL) { if (mCallback != nullptr) { newcbd = new CallbackData(this); newcbd = sp<CallbackData>::make(wp<AudioOutput>::fromExisting(this)); t = new AudioTrack( t = new AudioTrack( mStreamType, mStreamType, sampleRate, sampleRate, Loading @@ -2193,7 +2191,6 @@ status_t MediaPlayerService::AudioOutput::open( channelMask, channelMask, frameCount, frameCount, flags, flags, CallbackWrapper, newcbd, newcbd, 0, // notification frames 0, // notification frames mSessionId, mSessionId, Loading Loading @@ -2237,8 +2234,7 @@ status_t MediaPlayerService::AudioOutput::open( t->setCallerName("media"); t->setCallerName("media"); if ((t == 0) || (t->initCheck() != NO_ERROR)) { if ((t == 0) || (t->initCheck() != NO_ERROR)) { ALOGE("Unable to create audio track"); ALOGE("Unable to create audio track"); delete newcbd; // t, newcbd goes out of scope, so reference count drops to zero // t goes out of scope, so reference count drops to zero return NO_INIT; return NO_INIT; } else { } else { // successful AudioTrack initialization implies a legacy stream type was generated // successful AudioTrack initialization implies a legacy stream type was generated Loading Loading @@ -2272,7 +2268,6 @@ status_t MediaPlayerService::AudioOutput::open( if (mCallbackData != NULL) { if (mCallbackData != NULL) { mCallbackData->setOutput(this); mCallbackData->setOutput(this); } } delete newcbd; return updateTrack(); return updateTrack(); } } } } Loading Loading @@ -2378,7 +2373,7 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() { if (mCallbackData != NULL) { if (mCallbackData != NULL) { // two alternative approaches // two alternative approaches #if 1 #if 1 CallbackData *callbackData = mCallbackData; sp<CallbackData> callbackData = mCallbackData; mLock.unlock(); mLock.unlock(); // proper acquisition sequence // proper acquisition sequence callbackData->lock(); callbackData->lock(); Loading Loading @@ -2415,9 +2410,8 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() { // for example, the next player could be prepared and seeked. // for example, the next player could be prepared and seeked. // // // Presuming it isn't advisable to force the track over. // Presuming it isn't advisable to force the track over. if (mNextOutput->mTrack == NULL) { if (mNextOutput->mTrack == nullptr) { ALOGD("Recycling track for gapless playback"); ALOGD("Recycling track for gapless playback"); delete mNextOutput->mCallbackData; mNextOutput->mCallbackData = mCallbackData; mNextOutput->mCallbackData = mCallbackData; mNextOutput->mRecycledTrack = mTrack; mNextOutput->mRecycledTrack = mTrack; mNextOutput->mSampleRateHz = mSampleRateHz; mNextOutput->mSampleRateHz = mSampleRateHz; Loading @@ -2425,11 +2419,11 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() { mNextOutput->mFlags = mFlags; mNextOutput->mFlags = mFlags; mNextOutput->mFrameSize = mFrameSize; mNextOutput->mFrameSize = mFrameSize; close_l(); close_l(); mCallbackData = NULL; // destruction handled by mNextOutput mCallbackData.clear(); } else { } else { ALOGW("Ignoring gapless playback because next player has already started"); ALOGW("Ignoring gapless playback because next player has already started"); // remove track in case resource needed for future players. // remove track in case resource needed for future players. if (mCallbackData != NULL) { if (mCallbackData != nullptr) { mCallbackData->endTrackSwitch(); // release lock for callbacks before close. mCallbackData->endTrackSwitch(); // release lock for callbacks before close. } } close_l(); close_l(); Loading Loading @@ -2656,29 +2650,16 @@ sp<VolumeShaper::State> MediaPlayerService::AudioOutput::getVolumeShaperState(in } } } } // static size_t MediaPlayerService::AudioOutput::CallbackData::onMoreData(const AudioTrack::Buffer& buffer) { void MediaPlayerService::AudioOutput::CallbackWrapper( ALOGD("data callback"); int event, void *cookie, void *info) { lock(); //ALOGV("callbackwrapper"); sp<AudioOutput> me = getOutput(); CallbackData *data = (CallbackData*)cookie; if (me == nullptr) { // lock to ensure we aren't caught in the middle of a track switch. unlock(); data->lock(); return 0; AudioOutput *me = data->getOutput(); AudioTrack::Buffer *buffer = (AudioTrack::Buffer *)info; if (me == NULL) { // no output set, likely because the track was scheduled to be reused // by another player, but the format turned out to be incompatible. data->unlock(); if (buffer != NULL) { buffer->size = 0; } return; } } switch(event) { case AudioTrack::EVENT_MORE_DATA: { size_t actualSize = (*me->mCallback)( size_t actualSize = (*me->mCallback)( me, buffer->raw, buffer->size, me->mCallbackCookie, me.get(), buffer.raw, buffer.size, me->mCallbackCookie, CB_EVENT_FILL_BUFFER); CB_EVENT_FILL_BUFFER); // Log when no data is returned from the callback. // Log when no data is returned from the callback. Loading @@ -2691,24 +2672,38 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( // nevertheless for power reasons, we don't want to see too many of these. // nevertheless for power reasons, we don't want to see too many of these. ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned"); ALOGV_IF(actualSize == 0 && buffer->size > 0, "callbackwrapper: empty buffer returned"); unlock(); return actualSize; } buffer->size = actualSize; void MediaPlayerService::AudioOutput::CallbackData::onStreamEnd() { } break; lock(); sp<AudioOutput> me = getOutput(); case AudioTrack::EVENT_STREAM_END: if (me == nullptr) { // currently only occurs for offloaded callbacks unlock(); return; } ALOGV("callbackwrapper: deliver EVENT_STREAM_END"); ALOGV("callbackwrapper: deliver EVENT_STREAM_END"); (*me->mCallback)(me, NULL /* buffer */, 0 /* size */, (*me->mCallback)(me.get(), NULL /* buffer */, 0 /* size */, me->mCallbackCookie, CB_EVENT_STREAM_END); me->mCallbackCookie, CB_EVENT_STREAM_END); break; unlock(); } case AudioTrack::EVENT_NEW_IAUDIOTRACK : void MediaPlayerService::AudioOutput::CallbackData::onNewIAudioTrack() { lock(); sp<AudioOutput> me = getOutput(); if (me == nullptr) { unlock(); return; } ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN"); ALOGV("callbackwrapper: deliver EVENT_TEAR_DOWN"); (*me->mCallback)(me, NULL /* buffer */, 0 /* size */, (*me->mCallback)(me.get(), NULL /* buffer */, 0 /* size */, me->mCallbackCookie, CB_EVENT_TEAR_DOWN); me->mCallbackCookie, CB_EVENT_TEAR_DOWN); break; unlock(); } case AudioTrack::EVENT_UNDERRUN: void MediaPlayerService::AudioOutput::CallbackData::onUnderrun() { // This occurs when there is no data available, typically // This occurs when there is no data available, typically // when there is a failure to supply data to the AudioTrack. It can also // when there is a failure to supply data to the AudioTrack. It can also // occur in non-offloaded mode when the audio device comes out of standby. // occur in non-offloaded mode when the audio device comes out of standby. Loading @@ -2719,13 +2714,7 @@ void MediaPlayerService::AudioOutput::CallbackWrapper( // The underrun event is sent once per track underrun; the condition is reset // The underrun event is sent once per track underrun; the condition is reset // when more data is sent to the AudioTrack. // when more data is sent to the AudioTrack. ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)"); ALOGD("callbackwrapper: EVENT_UNDERRUN (discarded)"); break; default: ALOGE("received unknown event type: %d inside CallbackWrapper !", event); } data->unlock(); } } audio_session_t MediaPlayerService::AudioOutput::getSessionId() const audio_session_t MediaPlayerService::AudioOutput::getSessionId() const Loading
media/libmediaplayerservice/MediaPlayerService.h +13 −7 Original line number Original line Diff line number Diff line Loading @@ -30,9 +30,11 @@ #include <media/AidlConversion.h> #include <media/AidlConversion.h> #include <media/AudioResamplerPublic.h> #include <media/AudioResamplerPublic.h> #include <media/AudioSystem.h> #include <media/AudioSystem.h> #include <media/AudioTrack.h> #include <media/MediaPlayerInterface.h> #include <media/MediaPlayerInterface.h> #include <media/Metadata.h> #include <media/Metadata.h> #include <media/stagefright/foundation/ABase.h> #include <media/stagefright/foundation/ABase.h> #include <mediautils/Synchronization.h> #include <android/content/AttributionSourceState.h> #include <android/content/AttributionSourceState.h> #include <system/audio.h> #include <system/audio.h> Loading @@ -41,7 +43,6 @@ namespace android { using content::AttributionSourceState; using content::AttributionSourceState; class AudioTrack; struct AVSyncSettings; struct AVSyncSettings; class DeathNotifier; class DeathNotifier; class IDataSource; class IDataSource; Loading Loading @@ -161,7 +162,7 @@ class MediaPlayerService : public BnMediaPlayerService sp<AudioOutput> mNextOutput; sp<AudioOutput> mNextOutput; AudioCallback mCallback; AudioCallback mCallback; void * mCallbackCookie; void * mCallbackCookie; CallbackData * mCallbackData; sp<CallbackData> mCallbackData; audio_stream_type_t mStreamType; audio_stream_type_t mStreamType; audio_attributes_t * mAttributes; audio_attributes_t * mAttributes; float mLeftVolume; float mLeftVolume; Loading Loading @@ -189,15 +190,15 @@ class MediaPlayerService : public BnMediaPlayerService // CallbackData is what is passed to the AudioTrack as the "user" data. // CallbackData is what is passed to the AudioTrack as the "user" data. // We need to be able to target this to a different Output on the fly, // We need to be able to target this to a different Output on the fly, // so we can't use the Output itself for this. // so we can't use the Output itself for this. class CallbackData { class CallbackData : public AudioTrack::IAudioTrackCallback { friend AudioOutput; friend AudioOutput; public: public: explicit CallbackData(AudioOutput *cookie) { explicit CallbackData(const wp<AudioOutput>& cookie) { mData = cookie; mData = cookie; mSwitching = false; mSwitching = false; } } AudioOutput * getOutput() const { return mData; } sp<AudioOutput> getOutput() const { return mData.load().promote(); } void setOutput(AudioOutput* newcookie) { mData = newcookie; } void setOutput(const wp<AudioOutput>& newcookie) { mData.store(newcookie); } // lock/unlock are used by the callback before accessing the payload of this object // lock/unlock are used by the callback before accessing the payload of this object void lock() const { mLock.lock(); } void lock() const { mLock.lock(); } void unlock() const { mLock.unlock(); } void unlock() const { mLock.unlock(); } Loading @@ -220,8 +221,13 @@ class MediaPlayerService : public BnMediaPlayerService } } mSwitching = false; mSwitching = false; } } protected: size_t onMoreData(const AudioTrack::Buffer& buffer) override; void onUnderrun() override; void onStreamEnd() override; void onNewIAudioTrack() override; private: private: AudioOutput * mData; mediautils::atomic_wp<AudioOutput> mData; mutable Mutex mLock; // a recursive mutex might make this unnecessary. mutable Mutex mLock; // a recursive mutex might make this unnecessary. bool mSwitching; bool mSwitching; DISALLOW_EVIL_CONSTRUCTORS(CallbackData); DISALLOW_EVIL_CONSTRUCTORS(CallbackData); Loading