summaryrefslogtreecommitdiff
path: root/libaudio/alsa_utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libaudio/alsa_utils.cpp')
-rw-r--r--libaudio/alsa_utils.cpp161
1 files changed, 106 insertions, 55 deletions
diff --git a/libaudio/alsa_utils.cpp b/libaudio/alsa_utils.cpp
index 2062cf6..0f50848 100644
--- a/libaudio/alsa_utils.cpp
+++ b/libaudio/alsa_utils.cpp
@@ -219,33 +219,6 @@ void HDMIAudioCaps::reset_l() {
mModes.clear();
}
-void HDMIAudioCaps::getRatesForAF(String8& rates) {
- Mutex::Autolock _l(mLock);
- rates.clear();
-
- // If the sink does not support basic audio, then it supports no audio.
- if (!mBasicAudioSupported)
- return;
-
- // Basic audio always supports from 32k through 38k.
- uint32_t tmp = kSR_32000 | kSR_44100 | kSR_48000;
-
- // To keep things simple, only report mode information for the PCM mode
- // which supports the maximum number of channels.
- ssize_t ndx = getMaxChModeNdx_l();
- if (ndx >= 0)
- tmp |= mModes[ndx].sr_bitmask;
-
- bool first = true;
- for (uint32_t i = 1; tmp; i <<= 1) {
- if (i & tmp) {
- rates.appendFormat(first ? "%d" : "|%d", srMaskToSR(i));
- first = false;
- tmp &= ~i;
- }
- }
-}
-
void HDMIAudioCaps::getFmtsForAF(String8& fmts) {
Mutex::Autolock _l(mLock);
fmts.clear();
@@ -316,29 +289,117 @@ void HDMIAudioCaps::getFmtsForAF(String8& fmts) {
#endif /* ALSA_UTILS_PRINT_FORMATS */
}
-void HDMIAudioCaps::getChannelMasksForAF(String8& masks) {
+/* static */
+HDMIAudioCaps::AudFormat HDMIAudioCaps::alsaFormatFromAndroidFormat(audio_format_t format)
+{
+ AudFormat alsaFormat = kFmtInvalid;
+ switch (audio_get_main_format(format)) {
+ case AUDIO_FORMAT_PCM: alsaFormat = kFmtLPCM; break;
+ case AUDIO_FORMAT_AC3: alsaFormat = kFmtAC3; break;
+ case AUDIO_FORMAT_E_AC3: alsaFormat = kFmtAC3; break; // FIXME should this be kFmtEAC3?
+ case AUDIO_FORMAT_DTS: alsaFormat = kFmtDTS; break;
+ case AUDIO_FORMAT_DTS_HD: alsaFormat = kFmtDTSHD; break;
+ case AUDIO_FORMAT_IEC61937: alsaFormat = kFmtLPCM; break;
+ default:
+ ALOGE("supportsFormat() says format %#x not supported", format);
+ break;
+ }
+ return alsaFormat;
+}
+
+const HDMIAudioCaps::Mode *HDMIAudioCaps::getModeForFormat(HDMIAudioCaps::AudFormat format)
+{
+ for (size_t i = 0; i < mModes.size(); ++i) {
+ if (mModes[i].fmt == format) {
+ return &mModes[i];
+ }
+ }
+ return nullptr;
+}
+
+void HDMIAudioCaps::getRatesForAF(String8& rates, audio_format_t format) {
Mutex::Autolock _l(mLock);
- masks.clear();
+ rates.clear();
// If the sink does not support basic audio, then it supports no audio.
if (!mBasicAudioSupported)
return;
- masks.append("AUDIO_CHANNEL_OUT_STEREO");
+ uint32_t tmp = 0;
+ // No format provided: returns rates for format with max channels
+ if (format == AUDIO_FORMAT_INVALID) {
+ ssize_t ndx = getMaxChModeNdx_l();
+ if (ndx >= 0)
+ tmp = mModes[ndx].sr_bitmask;
+ } else {
+ AudFormat alsaFormat = alsaFormatFromAndroidFormat(format);
+ if (alsaFormat == kFmtInvalid) {
+ return;
+ }
+ const Mode *mode = getModeForFormat(alsaFormat);
+ if (mode == nullptr) {
+ return;
+ }
+ tmp = mode->sr_bitmask;
+ }
+ bool first = true;
+ for (uint32_t i = 1; tmp; i <<= 1) {
+ if (i & tmp) {
+ rates.appendFormat(first ? "%d" : "|%d", srMaskToSR(i));
+ first = false;
+ tmp &= ~i;
+ }
+ }
+}
+
+void HDMIAudioCaps::getChannelMasksForAF(String8& masks, audio_format_t format) {
+ Mutex::Autolock _l(mLock);
+ masks.clear();
+ const Mode *mode = nullptr;
- // To keep things simple, only report mode information for the mode
- // which supports the maximum number of channels.
- ssize_t ndx = getMaxChModeNdx_l();
- if (ndx < 0)
+ // If the sink does not support basic audio, then it supports no audio.
+ if (!mBasicAudioSupported)
return;
- if (mModes[ndx].max_ch >= 6) {
- if (masks.length())
- masks.append("|");
+ if (format == AUDIO_FORMAT_INVALID) {
+ // To keep things simple, only report mode information for the mode
+ // which supports the maximum number of channels.
+ ssize_t ndx = getMaxChModeNdx_l();
+ if (ndx < 0)
+ return;
+ mode = &mModes[ndx];
+ } else {
+ AudFormat alsaFormat = alsaFormatFromAndroidFormat(format);
+ if (alsaFormat == kFmtInvalid) {
+ return;
+ }
+ mode = getModeForFormat(alsaFormat);
+ if (mode == nullptr) {
+ return;
+ }
+ }
- masks.append((mModes[ndx].max_ch >= 8)
- ? "AUDIO_CHANNEL_OUT_5POINT1|AUDIO_CHANNEL_OUT_7POINT1"
- : "AUDIO_CHANNEL_OUT_5POINT1");
+ if (mode != nullptr) {
+ // allow mono for non-pcm formats, e.g. AC3
+ if (mode->max_ch >= 1 && mode->fmt != kFmtLPCM) {
+ masks.append("AUDIO_CHANNEL_OUT_MONO");
+ }
+ if (mode->max_ch >= 2) {
+ if (masks.length()) masks.append("|");
+ masks.append("AUDIO_CHANNEL_OUT_STEREO");
+ }
+ if (mode->max_ch >= 4) {
+ if (masks.length()) masks.append("|");
+ masks.append("AUDIO_CHANNEL_OUT_QUAD");
+ }
+ if (mode->max_ch >= 6) {
+ if (masks.length()) masks.append("|");
+ masks.append("AUDIO_CHANNEL_OUT_5POINT1");
+ }
+ if (mode->max_ch >= 8) {
+ if (masks.length()) masks.append("|");
+ masks.append("AUDIO_CHANNEL_OUT_7POINT1");
+ }
}
}
@@ -368,21 +429,11 @@ bool HDMIAudioCaps::supportsFormat(audio_format_t format,
if (!mBasicAudioSupported)
return false;
- AudFormat alsaFormat;
- switch (audio_get_main_format(format)) {
- case AUDIO_FORMAT_PCM: alsaFormat = kFmtLPCM; break;
- case AUDIO_FORMAT_AC3: alsaFormat = kFmtAC3; break;
- case AUDIO_FORMAT_E_AC3: alsaFormat = kFmtAC3; break; // FIXME should this be kFmtEAC3?
- case AUDIO_FORMAT_DTS: alsaFormat = kFmtDTS; break;
- case AUDIO_FORMAT_DTS_HD: alsaFormat = kFmtDTSHD; break;
- case AUDIO_FORMAT_IEC61937:
- alsaFormat = kFmtLPCM;
- isIec958NonAudio = true;
- break;
- default:
- ALOGE("supportsFormat() says format %#x not supported", format);
- return false;
- }
+ AudFormat alsaFormat = alsaFormatFromAndroidFormat(format);
+ if (alsaFormat == kFmtInvalid)
+ return false;
+
+ isIec958NonAudio |= (format == AUDIO_FORMAT_IEC61937);
// EAC3 uses a PCM sample rate of 4X the base rate.
// We try to detect that situation and allow 4X rate even if the