diff options
author | Richard Fitzgerald <rf@opensource.wolfsonmicro.com> | 2013-05-13 11:52:24 +0100 |
---|---|---|
committer | Eric Laurent <elaurent@google.com> | 2013-07-24 18:39:05 -0700 |
commit | a527ffd3c2ce72048a8fae51cd399024af4439b9 (patch) | |
tree | 79424aff01ccaa60d8dbfd060bfce05d3b7bc129 | |
parent | cb2388428a54fb3040209b8134c1e2acec0801fb (diff) | |
download | hardware_libhardware_legacy-a527ffd3c2ce72048a8fae51cd399024af4439b9.zip hardware_libhardware_legacy-a527ffd3c2ce72048a8fae51cd399024af4439b9.tar.gz hardware_libhardware_legacy-a527ffd3c2ce72048a8fae51cd399024af4439b9.tar.bz2 |
Code changes for audio offload support
- Share existing offload output if compatible instead of
creating a new one. Hardware has limited number of
offload channels (possible only 1) so we must use as
few as possible
- Changes to routing handling for offloaded outputs
Change-Id: I11111d8f504828595bd8dbf66444cbd1202e7192
Signed-off-by: Eric Laurent <elaurent@google.com>
-rw-r--r-- | audio/AudioHardwareGeneric.h | 2 | ||||
-rw-r--r-- | audio/AudioHardwareStub.cpp | 4 | ||||
-rw-r--r-- | audio/AudioHardwareStub.h | 2 | ||||
-rw-r--r-- | audio/AudioPolicyManagerBase.cpp | 144 | ||||
-rw-r--r-- | include/hardware_legacy/AudioPolicyManagerBase.h | 14 |
5 files changed, 116 insertions, 50 deletions
diff --git a/audio/AudioHardwareGeneric.h b/audio/AudioHardwareGeneric.h index 7b41e95..55498dc 100644 --- a/audio/AudioHardwareGeneric.h +++ b/audio/AudioHardwareGeneric.h @@ -92,6 +92,8 @@ public: virtual status_t setParameters(const String8& keyValuePairs); virtual String8 getParameters(const String8& keys); virtual unsigned int getInputFramesLost() const { return 0; } + virtual status_t addAudioEffect(effect_handle_t effect) { return NO_ERROR; } + virtual status_t removeAudioEffect(effect_handle_t effect) { return NO_ERROR; } private: AudioHardwareGeneric *mAudioHardware; diff --git a/audio/AudioHardwareStub.cpp b/audio/AudioHardwareStub.cpp index 70a8309..1083889 100644 --- a/audio/AudioHardwareStub.cpp +++ b/audio/AudioHardwareStub.cpp @@ -204,6 +204,10 @@ String8 AudioStreamInStub::getParameters(const String8& keys) return param.toString(); } +AudioHardwareInterface* createAudioHardware(void) { + return new AudioHardwareStub(); +} + // ---------------------------------------------------------------------------- }; // namespace android diff --git a/audio/AudioHardwareStub.h b/audio/AudioHardwareStub.h index 0858f37..c5f7a80 100644 --- a/audio/AudioHardwareStub.h +++ b/audio/AudioHardwareStub.h @@ -58,6 +58,8 @@ public: virtual status_t setParameters(const String8& keyValuePairs) { return NO_ERROR;} virtual String8 getParameters(const String8& keys); virtual unsigned int getInputFramesLost() const { return 0; } + virtual status_t addAudioEffect(effect_handle_t effect) { return NO_ERROR; } + virtual status_t removeAudioEffect(effect_handle_t effect) { return NO_ERROR; } }; class AudioHardwareStub : public AudioHardwareBase diff --git a/audio/AudioPolicyManagerBase.cpp b/audio/AudioPolicyManagerBase.cpp index e6e498f..56ec96e 100644 --- a/audio/AudioPolicyManagerBase.cpp +++ b/audio/AudioPolicyManagerBase.cpp @@ -37,6 +37,7 @@ #include <hardware/audio.h> #include <math.h> #include <hardware_legacy/audio_policy_conf.h> +#include <cutils/properties.h> namespace android_audio_legacy { @@ -161,10 +162,12 @@ status_t AudioPolicyManagerBase::setDeviceConnectionState(audio_devices_t device // outputs must be closed after checkOutputForAllStrategies() is executed if (!outputs.isEmpty()) { for (size_t i = 0; i < outputs.size(); i++) { + AudioOutputDescriptor *desc = mOutputs.valueFor(outputs[i]); // close unused outputs after device disconnection or direct outputs that have been // opened by checkOutputsForDevice() to query dynamic parameters if ((state == AudioSystem::DEVICE_STATE_UNAVAILABLE) || - (mOutputs.valueFor(outputs[i])->mFlags & AUDIO_OUTPUT_FLAG_DIRECT)) { + (((desc->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) != 0) && + (desc->mDirectOpenCount == 0))) { closeOutput(outputs[i]); } } @@ -491,14 +494,24 @@ AudioPolicyManagerBase::IOProfile *AudioPolicyManagerBase::getProfileForDirectOu continue; } for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { - IOProfile *profile = mHwModules[i]->mOutputProfiles[j]; - if (profile->isCompatibleProfile(device, samplingRate, format, + IOProfile *profile = mHwModules[i]->mOutputProfiles[j]; + if (flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) { + if (profile->isCompatibleProfile(device, samplingRate, format, + channelMask, + AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD)) { + if (mAvailableOutputDevices & profile->mSupportedDevices) { + return mHwModules[i]->mOutputProfiles[j]; + } + } + } else if (flags & AUDIO_OUTPUT_FLAG_DIRECT) { + if (profile->isCompatibleProfile(device, samplingRate, format, channelMask, AUDIO_OUTPUT_FLAG_DIRECT)) { - if (mAvailableOutputDevices & profile->mSupportedDevices) { - return mHwModules[i]->mOutputProfiles[j]; - } - } + if (mAvailableOutputDevices & profile->mSupportedDevices) { + return mHwModules[i]->mOutputProfiles[j]; + } + } + } } } return 0; @@ -515,8 +528,8 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str uint32_t latency = 0; routing_strategy strategy = getStrategy((AudioSystem::stream_type)stream); audio_devices_t device = getDeviceForStrategy(strategy, false /*fromCache*/); - ALOGV("getOutput() stream %d, samplingRate %d, format %d, channelMask %x, flags %x", - stream, samplingRate, format, channelMask, flags); + ALOGV("getOutput() device %d, stream %d, samplingRate %d, format %x, channelMask %x, flags %x", + device, stream, samplingRate, format, channelMask, flags); #ifdef AUDIO_POLICY_TEST if (mCurOutput != 0) { @@ -552,6 +565,13 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str #endif //AUDIO_POLICY_TEST // open a direct output if required by specified parameters + //force direct flag if offload flag is set: offloading implies a direct output stream + // and all common behaviors are driven by checking only the direct flag + // this should normally be set appropriately in the policy configuration file + if ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { + flags = (AudioSystem::output_flags)(flags | AUDIO_OUTPUT_FLAG_DIRECT); + } + IOProfile *profile = getProfileForDirectOutput(device, samplingRate, format, @@ -569,7 +589,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str (format == outputDesc->mFormat) && (channelMask == outputDesc->mChannelMask)) { outputDesc->mDirectOpenCount++; - ALOGV("getOutput() reusing direct output %d", output); + ALOGV("getOutput() reusing direct output %d", mOutputs.keyAt(i)); return mOutputs.keyAt(i); } } @@ -584,8 +604,7 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str outputDesc->mFormat = (audio_format_t)format; outputDesc->mChannelMask = (audio_channel_mask_t)channelMask; outputDesc->mLatency = 0; - outputDesc->mFlags =(audio_output_flags_t) - (outputDesc->mFlags | flags | AUDIO_OUTPUT_FLAG_DIRECT); + outputDesc->mFlags =(audio_output_flags_t) (outputDesc->mFlags | flags); outputDesc->mRefCount[stream] = 0; outputDesc->mStopTime[stream] = 0; outputDesc->mDirectOpenCount = 1; @@ -595,7 +614,8 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str &outputDesc->mFormat, &outputDesc->mChannelMask, &outputDesc->mLatency, - outputDesc->mFlags); + outputDesc->mFlags, + offloadInfo); // only accept an output with the requested parameters if (output == 0 || @@ -622,13 +642,15 @@ audio_io_handle_t AudioPolicyManagerBase::getOutput(AudioSystem::stream_type str // open a non direct output - // get which output is suitable for the specified stream. The actual routing change will happen - // when startOutput() will be called - SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); + // for non direct outputs, only PCM is supported + if (audio_is_linear_pcm((audio_format_t)format)) { + // get which output is suitable for the specified stream. The actual + // routing change will happen when startOutput() will be called + SortedVector<audio_io_handle_t> outputs = getOutputsForDevice(device, mOutputs); - output = selectOutput(outputs, flags); - - ALOGW_IF((output ==0), "getOutput() could not find output for stream %d, samplingRate %d," + output = selectOutput(outputs, flags); + } + ALOGW_IF((output == 0), "getOutput() could not find output for stream %d, samplingRate %d," "format %d, channels %x, flags %x", stream, samplingRate, format, channelMask, flags); ALOGV("getOutput() returns output %d", output); @@ -790,7 +812,7 @@ status_t AudioPolicyManagerBase::stopOutput(audio_io_handle_t output, if (curOutput != output && desc->isActive() && outputDesc->sharesHwModuleWith(desc) && - newDevice != desc->device()) { + (newDevice != desc->device())) { setOutputDevice(curOutput, getNewDevice(curOutput, false /*fromCache*/), true, @@ -841,7 +863,6 @@ void AudioPolicyManagerBase::releaseOutput(audio_io_handle_t output) closeOutput(output); } } - } audio_io_handle_t AudioPolicyManagerBase::getInput(int inputSource, @@ -1319,10 +1340,54 @@ status_t AudioPolicyManagerBase::dump(int fd) return NO_ERROR; } +// This function checks for the parameters which can be offloaded. +// This can be enhanced depending on the capability of the DSP and policy +// of the system. bool AudioPolicyManagerBase::isOffloadSupported(const audio_offload_info_t& offloadInfo) { - // Stub implementation - return false; + ALOGV("isOffloadSupported: SR=%u, CM=0x%x, Format=0x%x, StreamType=%d," + " BitRate=%u, duration=%lld us, has_video=%d", + offloadInfo.sample_rate, offloadInfo.channel_mask, + offloadInfo.format, + offloadInfo.stream_type, offloadInfo.bit_rate, offloadInfo.duration_us, + offloadInfo.has_video); + + // Check if offload has been disabled + char propValue[PROPERTY_VALUE_MAX]; + if (property_get("audio.offload.disable", propValue, "0")) { + if (atoi(propValue) != 0) { + ALOGV("offload disabled by audio.offload.disable=%s", propValue ); + return false; + } + } + + // Check if stream type is music, then only allow offload as of now. + if (offloadInfo.stream_type != AUDIO_STREAM_MUSIC) + { + ALOGV("isOffloadSupported: stream_type != MUSIC returning false"); + return false; + } + + //If duration is less than minimum value defined in property, return false + if (property_get("audio.offload.min.duration.secs", propValue, NULL)) { + if (offloadInfo.duration_us < (atoi(propValue) * 1000000 )) { + ALOGV("Offload denied by duration < audio.offload.min.duration.secs(=%s)", propValue); + return false; + } + } else if (offloadInfo.duration_us < OFFLOAD_DEFAULT_MIN_DURATION_SECS * 1000000) { + ALOGV("Offload denied by duration < default min(=%u)", OFFLOAD_DEFAULT_MIN_DURATION_SECS); + return false; + } + + // See if there is a profile to support this. + // AUDIO_DEVICE_NONE + IOProfile *profile = getProfileForDirectOutput(AUDIO_DEVICE_NONE /*ignore device */, + offloadInfo.sample_rate, + offloadInfo.format, + offloadInfo.channel_mask, + AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD); + ALOGV("isOffloadSupported() profile %sfound", profile != NULL ? "" : "NOT "); + return (profile != NULL); } // ---------------------------------------------------------------------------- @@ -1368,11 +1433,14 @@ AudioPolicyManagerBase::AudioPolicyManagerBase(AudioPolicyClientInterface *clien continue; } // open all output streams needed to access attached devices + // except for direct output streams that are only opened when they are actually + // required by an app. for (size_t j = 0; j < mHwModules[i]->mOutputProfiles.size(); j++) { const IOProfile *outProfile = mHwModules[i]->mOutputProfiles[j]; - if (outProfile->mSupportedDevices & mAttachedOutputDevices) { + if ((outProfile->mSupportedDevices & mAttachedOutputDevices) && + ((outProfile->mFlags & AUDIO_OUTPUT_FLAG_DIRECT) == 0)) { AudioOutputDescriptor *outputDesc = new AudioOutputDescriptor(outProfile); outputDesc->mDevice = (audio_devices_t)(mDefaultOutputDevice & outProfile->mSupportedDevices); @@ -3011,17 +3079,6 @@ bool AudioPolicyManagerBase::isStateInCall(int state) { (state == AudioSystem::MODE_IN_COMMUNICATION)); } -bool AudioPolicyManagerBase::needsDirectOuput(audio_stream_type_t stream, - uint32_t samplingRate, - audio_format_t format, - audio_channel_mask_t channelMask, - audio_output_flags_t flags, - audio_devices_t device) -{ - return ((flags & AudioSystem::OUTPUT_FLAG_DIRECT) || - (format != 0 && !AudioSystem::isLinearPCM(format))); -} - uint32_t AudioPolicyManagerBase::getMaxEffectsCpuLoad() { return MAX_EFFECTS_CPU_LOAD; @@ -3164,7 +3221,7 @@ status_t AudioPolicyManagerBase::AudioOutputDescriptor::dump(int fd) snprintf(buffer, SIZE, " Sampling rate: %d\n", mSamplingRate); result.append(buffer); - snprintf(buffer, SIZE, " Format: %d\n", mFormat); + snprintf(buffer, SIZE, " Format: %08x\n", mFormat); result.append(buffer); snprintf(buffer, SIZE, " Channels: %08x\n", mChannelMask); result.append(buffer); @@ -3402,7 +3459,7 @@ void AudioPolicyManagerBase::IOProfile::dump(int fd) snprintf(buffer, SIZE, " - channel masks: "); result.append(buffer); for (size_t i = 0; i < mChannelMasks.size(); i++) { - snprintf(buffer, SIZE, "%04x", mChannelMasks[i]); + snprintf(buffer, SIZE, "0x%04x", mChannelMasks[i]); result.append(buffer); result.append(i == (mChannelMasks.size() - 1) ? "\n" : ", "); } @@ -3410,14 +3467,14 @@ void AudioPolicyManagerBase::IOProfile::dump(int fd) snprintf(buffer, SIZE, " - formats: "); result.append(buffer); for (size_t i = 0; i < mFormats.size(); i++) { - snprintf(buffer, SIZE, "%d", mFormats[i]); + snprintf(buffer, SIZE, "0x%08x", mFormats[i]); result.append(buffer); result.append(i == (mFormats.size() - 1) ? "\n" : ", "); } - snprintf(buffer, SIZE, " - devices: %04x\n", mSupportedDevices); + snprintf(buffer, SIZE, " - devices: 0x%04x\n", mSupportedDevices); result.append(buffer); - snprintf(buffer, SIZE, " - flags: %04x\n", mFlags); + snprintf(buffer, SIZE, " - flags: 0x%04x\n", mFlags); result.append(buffer); write(fd, result.string(), result.size()); @@ -3518,6 +3575,13 @@ audio_output_flags_t AudioPolicyManagerBase::parseFlagNames(char *name) } flagName = strtok(NULL, "|"); } + //force direct flag if offload flag is set: offloading implies a direct output stream + // and all common behaviors are driven by checking only the direct flag + // this should normally be set appropriately in the policy configuration file + if ((flag & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) != 0) { + flag |= AUDIO_OUTPUT_FLAG_DIRECT; + } + return (audio_output_flags_t)flag; } diff --git a/include/hardware_legacy/AudioPolicyManagerBase.h b/include/hardware_legacy/AudioPolicyManagerBase.h index cb2a7fa..e580e1e 100644 --- a/include/hardware_legacy/AudioPolicyManagerBase.h +++ b/include/hardware_legacy/AudioPolicyManagerBase.h @@ -52,6 +52,10 @@ namespace android_audio_legacy { #define NUM_VOL_CURVE_KNEES 2 +// Default minimum length allowed for offloading a compressed track +// Can be overridden by the audio.offload.min.duration.secs property +#define OFFLOAD_DEFAULT_MIN_DURATION_SECS 5 + // ---------------------------------------------------------------------------- // AudioPolicyManagerBase implements audio policy manager behavior common to all platforms. // Each platform must implement an AudioPolicyManager class derived from AudioPolicyManagerBase @@ -444,16 +448,6 @@ protected: void updateDevicesAndOutputs(); - // true if current platform requires a specific output to be opened for this particular - // set of parameters. This function is called by getOutput() and is implemented by platform - // specific audio policy manager. - virtual bool needsDirectOuput(audio_stream_type_t stream, - uint32_t samplingRate, - audio_format_t format, - audio_channel_mask_t channelMask, - audio_output_flags_t flags, - audio_devices_t device); - virtual uint32_t getMaxEffectsCpuLoad(); virtual uint32_t getMaxEffectsMemory(); #ifdef AUDIO_POLICY_TEST |