AudioTrack: support ENCODING_IEC61937
Set DIRECT flag.
Use audio_has_proportional_frames() instead of audio_is_linear_pcm()
where appropriate.
Bug: 24541671
Bug: 20891646
Bug: 26373761
Change-Id: Ia32036b18683b084d6c9887593df87397ea0afd9
Signed-off-by: Phil Burk <philburk@google.com>
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index e17e47e..b2a5f14 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -363,6 +363,8 @@
// these below should probably come from the audioFlinger too...
if (format == AUDIO_FORMAT_DEFAULT) {
format = AUDIO_FORMAT_PCM_16_BIT;
+ } else if (format == AUDIO_FORMAT_IEC61937) { // HDMI pass-through?
+ mAttributes.flags |= AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO;
}
// validate parameters
@@ -398,13 +400,13 @@
}
if (flags & AUDIO_OUTPUT_FLAG_DIRECT) {
- if (audio_is_linear_pcm(format)) {
+ if (audio_has_proportional_frames(format)) {
mFrameSize = channelCount * audio_bytes_per_sample(format);
} else {
mFrameSize = sizeof(uint8_t);
}
} else {
- ALOG_ASSERT(audio_is_linear_pcm(format));
+ ALOG_ASSERT(audio_has_proportional_frames(format));
mFrameSize = channelCount * audio_bytes_per_sample(format);
// createTrack will return an error if PCM format is not supported by server,
// so no need to check for specific PCM formats here
@@ -1221,7 +1223,7 @@
mNotificationFramesAct = mNotificationFramesReq;
size_t frameCount = mReqFrameCount;
- if (!audio_is_linear_pcm(mFormat)) {
+ if (!audio_has_proportional_frames(mFormat)) {
if (mSharedBuffer != 0) {
// Same comment as below about ignoring frameCount parameter for set()
@@ -1944,7 +1946,7 @@
return NS_NEVER;
}
- if (mRetryOnPartialBuffer && audio_is_linear_pcm(mFormat)) {
+ if (mRetryOnPartialBuffer && audio_has_proportional_frames(mFormat)) {
mRetryOnPartialBuffer = false;
if (avail < mRemainingFrames) {
if (ns > 0) { // account for obtain time
@@ -1990,7 +1992,7 @@
// buffer size and skip the loop entirely.
nsecs_t myns;
- if (audio_is_linear_pcm(mFormat)) {
+ if (audio_has_proportional_frames(mFormat)) {
// time to wait based on buffer occupancy
const nsecs_t datans = mRemainingFrames <= avail ? 0 :
framesToNanoseconds(mRemainingFrames - avail, sampleRate, speed);
diff --git a/services/audioflinger/AudioFlinger.cpp b/services/audioflinger/AudioFlinger.cpp
index 6f34271..4ee8d6c 100644
--- a/services/audioflinger/AudioFlinger.cpp
+++ b/services/audioflinger/AudioFlinger.cpp
@@ -107,7 +107,7 @@
// ----------------------------------------------------------------------------
const char *formatToString(audio_format_t format) {
- switch (format & AUDIO_FORMAT_MAIN_MASK) {
+ switch (audio_get_main_format(format)) {
case AUDIO_FORMAT_PCM:
switch (format) {
case AUDIO_FORMAT_PCM_16_BIT: return "pcm16";
@@ -130,6 +130,7 @@
case AUDIO_FORMAT_OPUS: return "opus";
case AUDIO_FORMAT_AC3: return "ac-3";
case AUDIO_FORMAT_E_AC3: return "e-ac-3";
+ case AUDIO_FORMAT_IEC61937: return "iec61937";
default:
break;
}
@@ -1162,7 +1163,7 @@
return 0;
}
if ((sampleRate == 0) ||
- !audio_is_valid_format(format) || !audio_is_linear_pcm(format) ||
+ !audio_is_valid_format(format) || !audio_has_proportional_frames(format) ||
!audio_is_input_channel(channelMask)) {
return 0;
}
diff --git a/services/audioflinger/AudioHwDevice.cpp b/services/audioflinger/AudioHwDevice.cpp
index 3191598..7494930 100644
--- a/services/audioflinger/AudioHwDevice.cpp
+++ b/services/audioflinger/AudioHwDevice.cpp
@@ -68,7 +68,7 @@
status);
// If the data is encoded then try again using wrapped PCM.
- bool wrapperNeeded = !audio_is_linear_pcm(originalConfig.format)
+ bool wrapperNeeded = !audio_has_proportional_frames(originalConfig.format)
&& ((flags & AUDIO_OUTPUT_FLAG_DIRECT) != 0)
&& ((flags & AUDIO_OUTPUT_FLAG_COMPRESS_OFFLOAD) == 0);
diff --git a/services/audioflinger/AudioStreamOut.cpp b/services/audioflinger/AudioStreamOut.cpp
index b6d1be7..6026bbb 100644
--- a/services/audioflinger/AudioStreamOut.cpp
+++ b/services/audioflinger/AudioStreamOut.cpp
@@ -35,7 +35,7 @@
, mFramesWrittenAtStandby(0)
, mRenderPosition(0)
, mRateMultiplier(1)
- , mHalFormatIsLinearPcm(false)
+ , mHalFormatHasProportionalFrames(false)
, mHalFrameSize(0)
{
}
@@ -96,7 +96,7 @@
// Adjust for standby using HAL rate frames.
// Only apply this correction if the HAL is getting PCM frames.
- if (mHalFormatIsLinearPcm) {
+ if (mHalFormatHasProportionalFrames) {
uint64_t adjustedPosition = (halPosition <= mFramesWrittenAtStandby) ?
0 : (halPosition - mFramesWrittenAtStandby);
// Scale from HAL sample rate to application rate.
@@ -116,16 +116,21 @@
const char *address)
{
audio_stream_out_t *outStream;
+
+ audio_output_flags_t customFlags = (config->format == AUDIO_FORMAT_IEC61937)
+ ? (audio_output_flags_t)(flags | AUDIO_OUTPUT_FLAG_IEC958_NONAUDIO)
+ : flags;
+
int status = hwDev()->open_output_stream(
hwDev(),
handle,
devices,
- flags,
+ customFlags,
config,
&outStream,
address);
- ALOGV("AudioStreamOut::open(), HAL open_output_stream returned "
- " %p, sampleRate %d, Format %#x, "
+ ALOGV("AudioStreamOut::open(), HAL returned "
+ " stream %p, sampleRate %d, Format %#x, "
"channelMask %#x, status %d",
outStream,
config->sample_rate,
@@ -133,10 +138,26 @@
config->channel_mask,
status);
+ // Some HALs may not recognize AUDIO_FORMAT_IEC61937. But if we declare
+ // it as PCM then it will probably work.
+ if (status != NO_ERROR && config->format == AUDIO_FORMAT_IEC61937) {
+ struct audio_config customConfig = *config;
+ customConfig.format = AUDIO_FORMAT_PCM_16_BIT;
+
+ status = hwDev()->open_output_stream(
+ hwDev(),
+ handle,
+ devices,
+ customFlags,
+ &customConfig,
+ &outStream,
+ address);
+ ALOGV("AudioStreamOut::open(), treat IEC61937 as PCM, status = %d", status);
+ }
+
if (status == NO_ERROR) {
stream = outStream;
- mHalFormatIsLinearPcm = audio_is_linear_pcm(config->format);
- ALOGI("AudioStreamOut::open(), mHalFormatIsLinearPcm = %d", (int)mHalFormatIsLinearPcm);
+ mHalFormatHasProportionalFrames = audio_has_proportional_frames(config->format);
mHalFrameSize = audio_stream_out_frame_size(stream);
}
diff --git a/services/audioflinger/AudioStreamOut.h b/services/audioflinger/AudioStreamOut.h
index 06a2277..768f537 100644
--- a/services/audioflinger/AudioStreamOut.h
+++ b/services/audioflinger/AudioStreamOut.h
@@ -106,7 +106,7 @@
uint64_t mFramesWrittenAtStandby;
uint64_t mRenderPosition; // reset by flush or standby
int mRateMultiplier;
- bool mHalFormatIsLinearPcm;
+ bool mHalFormatHasProportionalFrames;
size_t mHalFrameSize;
};
diff --git a/services/audioflinger/Threads.cpp b/services/audioflinger/Threads.cpp
index 2fd5758..cfac81d 100644
--- a/services/audioflinger/Threads.cpp
+++ b/services/audioflinger/Threads.cpp
@@ -1815,7 +1815,7 @@
// This is probably too conservative, but legacy application code may depend on it.
// If you change this calculation, also review the start threshold which is related.
if (!(*flags & IAudioFlinger::TRACK_FAST)
- && audio_is_linear_pcm(format) && sharedBuffer == 0) {
+ && audio_has_proportional_frames(format) && sharedBuffer == 0) {
// this must match AudioTrack.cpp calculateMinFrameCount().
// TODO: Move to a common library
uint32_t latencyMs = mOutput->stream->get_latency(mOutput->stream);
@@ -1838,7 +1838,7 @@
switch (mType) {
case DIRECT:
- if (audio_is_linear_pcm(format)) {
+ if (audio_is_linear_pcm(format)) { // TODO maybe use audio_has_proportional_frames()?
if (sampleRate != mSampleRate || format != mFormat || channelMask != mChannelMask) {
ALOGE("createTrack_l() Bad parameter: sampleRate %u format %#x, channelMask 0x%08x "
"for output %p with format %#x",
@@ -4715,7 +4715,7 @@
// Do not use a high threshold for compressed audio.
uint32_t minFrames;
if ((track->sharedBuffer() == 0) && !track->isStopping_1() && !track->isPausing()
- && (track->mRetryCount > 1) && audio_is_linear_pcm(mFormat)) {
+ && (track->mRetryCount > 1) && audio_has_proportional_frames(mFormat)) {
minFrames = mNormalFrameCount;
} else {
minFrames = 1;
@@ -4776,7 +4776,7 @@
// We have consumed all the buffers of this track.
// Remove it from the list of active tracks.
size_t audioHALFrames;
- if (audio_is_linear_pcm(mFormat)) {
+ if (audio_has_proportional_frames(mFormat)) {
audioHALFrames = (latency_l() * mSampleRate) / 1000;
} else {
audioHALFrames = 0;
@@ -4884,7 +4884,7 @@
} else {
mSleepTimeUs = mIdleSleepTimeUs;
}
- } else if (mBytesWritten != 0 && audio_is_linear_pcm(mFormat)) {
+ } else if (mBytesWritten != 0 && audio_has_proportional_frames(mFormat)) {
memset(mSinkBuffer, 0, mFrameCount * mFrameSize);
mSleepTimeUs = 0;
}
@@ -4991,7 +4991,7 @@
uint32_t AudioFlinger::DirectOutputThread::activeSleepTimeUs() const
{
uint32_t time;
- if (audio_is_linear_pcm(mFormat)) {
+ if (audio_has_proportional_frames(mFormat)) {
time = PlaybackThread::activeSleepTimeUs();
} else {
time = 10000;
@@ -5002,7 +5002,7 @@
uint32_t AudioFlinger::DirectOutputThread::idleSleepTimeUs() const
{
uint32_t time;
- if (audio_is_linear_pcm(mFormat)) {
+ if (audio_has_proportional_frames(mFormat)) {
time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000) / 2;
} else {
time = 10000;
@@ -5013,7 +5013,7 @@
uint32_t AudioFlinger::DirectOutputThread::suspendSleepTimeUs() const
{
uint32_t time;
- if (audio_is_linear_pcm(mFormat)) {
+ if (audio_has_proportional_frames(mFormat)) {
time = (uint32_t)(((mFrameCount * 1000) / mSampleRate) * 1000);
} else {
time = 10000;
@@ -5030,7 +5030,7 @@
// no delay on outputs with HW A/V sync
if (usesHwAvSync()) {
mStandbyDelayNs = 0;
- } else if ((mType == OFFLOAD) && !audio_is_linear_pcm(mFormat)) {
+ } else if ((mType == OFFLOAD) && !audio_has_proportional_frames(mFormat)) {
mStandbyDelayNs = kOffloadStandbyDelayNs;
} else {
mStandbyDelayNs = microseconds(mActiveSleepTimeUs*2);
diff --git a/services/audioflinger/Tracks.cpp b/services/audioflinger/Tracks.cpp
index b4c1fdd..5e5920f 100644
--- a/services/audioflinger/Tracks.cpp
+++ b/services/audioflinger/Tracks.cpp
@@ -85,7 +85,7 @@
mChannelCount(isOut ?
audio_channel_count_from_out_mask(channelMask) :
audio_channel_count_from_in_mask(channelMask)),
- mFrameSize(audio_is_linear_pcm(format) ?
+ mFrameSize(audio_has_proportional_frames(format) ?
mChannelCount * audio_bytes_per_sample(format) : sizeof(int8_t)),
mFrameCount(frameCount),
mSessionId(sessionId),
diff --git a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
index 58eaf79..f613f94 100644
--- a/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
+++ b/services/audiopolicy/common/managerdefinitions/src/TypeConverter.cpp
@@ -137,6 +137,7 @@
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_E_AC3),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS),
MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_DTS_HD),
+ MAKE_STRING_FROM_ENUM(AUDIO_FORMAT_IEC61937),
};
template<>
const size_t FormatConverter::mSize = sizeof(FormatConverter::mTable) /
diff --git a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
index ec70ed4..a5b1e47 100644
--- a/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
+++ b/services/audiopolicy/managerdefault/AudioPolicyManager.cpp
@@ -711,7 +711,7 @@
sp<SwAudioOutputDescriptor> desc;
if (mPolicyMixes.getOutputForAttr(attributes, desc) == NO_ERROR) {
ALOG_ASSERT(desc != 0, "Invalid desc returned by getOutputForAttr");
- if (!audio_is_linear_pcm(format)) {
+ if (!audio_has_proportional_frames(format)) {
return BAD_VALUE;
}
*stream = streamTypefromAttributesInt(&attributes);