Merge commit 'fcae6c71794696a074cabf20beeb02fd87853e30' into eclair-mr2-plus-aosp * commit 'fcae6c71794696a074cabf20beeb02fd87853e30': Fix issue 2203561: Sholes: audio playing out of earpiece.
This commit is contained in:
@ -79,7 +79,7 @@ static void android_media_ToneGenerator_release(JNIEnv *env, jobject thiz) {
|
|||||||
|
|
||||||
static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz,
|
static void android_media_ToneGenerator_native_setup(JNIEnv *env, jobject thiz,
|
||||||
jint streamType, jint volume) {
|
jint streamType, jint volume) {
|
||||||
ToneGenerator *lpToneGen = new ToneGenerator(streamType, AudioSystem::linearToLog(volume));
|
ToneGenerator *lpToneGen = new ToneGenerator(streamType, AudioSystem::linearToLog(volume), true);
|
||||||
|
|
||||||
env->SetIntField(thiz, fields.context, 0);
|
env->SetIntField(thiz, fields.context, 0);
|
||||||
|
|
||||||
|
@ -314,6 +314,11 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool processAudioBuffer(const sp<ClientRecordThread>& thread);
|
bool processAudioBuffer(const sp<ClientRecordThread>& thread);
|
||||||
|
status_t openRecord(uint32_t sampleRate,
|
||||||
|
int format,
|
||||||
|
int channelCount,
|
||||||
|
int frameCount,
|
||||||
|
uint32_t flags);
|
||||||
|
|
||||||
sp<IAudioRecord> mAudioRecord;
|
sp<IAudioRecord> mAudioRecord;
|
||||||
sp<IMemory> mCblkMemory;
|
sp<IMemory> mCblkMemory;
|
||||||
@ -341,6 +346,7 @@ private:
|
|||||||
uint32_t mNewPosition;
|
uint32_t mNewPosition;
|
||||||
uint32_t mUpdatePeriod;
|
uint32_t mUpdatePeriod;
|
||||||
audio_io_handle_t mInput;
|
audio_io_handle_t mInput;
|
||||||
|
uint32_t mFlags;
|
||||||
};
|
};
|
||||||
|
|
||||||
}; // namespace android
|
}; // namespace android
|
||||||
|
@ -391,6 +391,14 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool processAudioBuffer(const sp<AudioTrackThread>& thread);
|
bool processAudioBuffer(const sp<AudioTrackThread>& thread);
|
||||||
|
status_t createTrack(int streamType,
|
||||||
|
uint32_t sampleRate,
|
||||||
|
int format,
|
||||||
|
int channelCount,
|
||||||
|
int frameCount,
|
||||||
|
uint32_t flags,
|
||||||
|
const sp<IMemory>& sharedBuffer,
|
||||||
|
audio_io_handle_t output);
|
||||||
|
|
||||||
sp<IAudioTrack> mAudioTrack;
|
sp<IAudioTrack> mAudioTrack;
|
||||||
sp<IMemory> mCblkMemory;
|
sp<IMemory> mCblkMemory;
|
||||||
|
@ -151,7 +151,7 @@ public:
|
|||||||
NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
|
NUM_SUP_TONES = LAST_SUP_TONE-FIRST_SUP_TONE+1
|
||||||
};
|
};
|
||||||
|
|
||||||
ToneGenerator(int streamType, float volume);
|
ToneGenerator(int streamType, float volume, bool threadCanCallJava = false);
|
||||||
~ToneGenerator();
|
~ToneGenerator();
|
||||||
|
|
||||||
bool startTone(int toneType, int durationMs = -1);
|
bool startTone(int toneType, int durationMs = -1);
|
||||||
@ -242,6 +242,7 @@ private:
|
|||||||
|
|
||||||
static const ToneDescriptor sToneDescriptors[];
|
static const ToneDescriptor sToneDescriptors[];
|
||||||
|
|
||||||
|
bool mThreadCanCallJava;
|
||||||
unsigned int mTotalSmp; // Total number of audio samples played (gives current time)
|
unsigned int mTotalSmp; // Total number of audio samples played (gives current time)
|
||||||
unsigned int mNextSegSmp; // Position of next segment transition expressed in samples
|
unsigned int mNextSegSmp; // Position of next segment transition expressed in samples
|
||||||
// NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly
|
// NOTE: because mTotalSmp, mNextSegSmp are stored on 32 bit, current design will operate properly
|
||||||
|
@ -101,11 +101,6 @@ status_t AudioRecord::set(
|
|||||||
return INVALID_OPERATION;
|
return INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
|
|
||||||
if (audioFlinger == 0) {
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (inputSource == AUDIO_SOURCE_DEFAULT) {
|
if (inputSource == AUDIO_SOURCE_DEFAULT) {
|
||||||
inputSource = AUDIO_SOURCE_MIC;
|
inputSource = AUDIO_SOURCE_MIC;
|
||||||
}
|
}
|
||||||
@ -171,22 +166,14 @@ status_t AudioRecord::set(
|
|||||||
notificationFrames = frameCount/2;
|
notificationFrames = frameCount/2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// open record channel
|
// create the IAudioRecord
|
||||||
status_t status;
|
status_t status = openRecord(sampleRate, format, channelCount,
|
||||||
sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
|
frameCount, flags);
|
||||||
sampleRate, format,
|
|
||||||
channelCount,
|
if (status != NO_ERROR) {
|
||||||
frameCount,
|
|
||||||
((uint16_t)flags) << 16,
|
|
||||||
&status);
|
|
||||||
if (record == 0) {
|
|
||||||
LOGE("AudioFlinger could not create record track, status: %d", status);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
sp<IMemory> cblk = record->getCblk();
|
|
||||||
if (cblk == 0) {
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
if (cbf != 0) {
|
if (cbf != 0) {
|
||||||
mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
|
mClientRecordThread = new ClientRecordThread(*this, threadCanCallJava);
|
||||||
if (mClientRecordThread == 0) {
|
if (mClientRecordThread == 0) {
|
||||||
@ -196,11 +183,6 @@ status_t AudioRecord::set(
|
|||||||
|
|
||||||
mStatus = NO_ERROR;
|
mStatus = NO_ERROR;
|
||||||
|
|
||||||
mAudioRecord = record;
|
|
||||||
mCblkMemory = cblk;
|
|
||||||
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
|
|
||||||
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
|
|
||||||
mCblk->out = 0;
|
|
||||||
mFormat = format;
|
mFormat = format;
|
||||||
// Update buffer size in case it has been limited by AudioFlinger during track creation
|
// Update buffer size in case it has been limited by AudioFlinger during track creation
|
||||||
mFrameCount = mCblk->frameCount;
|
mFrameCount = mCblk->frameCount;
|
||||||
@ -217,6 +199,7 @@ status_t AudioRecord::set(
|
|||||||
mNewPosition = 0;
|
mNewPosition = 0;
|
||||||
mUpdatePeriod = 0;
|
mUpdatePeriod = 0;
|
||||||
mInputSource = (uint8_t)inputSource;
|
mInputSource = (uint8_t)inputSource;
|
||||||
|
mFlags = flags;
|
||||||
|
|
||||||
return NO_ERROR;
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
@ -284,15 +267,26 @@ status_t AudioRecord::start()
|
|||||||
if (android_atomic_or(1, &mActive) == 0) {
|
if (android_atomic_or(1, &mActive) == 0) {
|
||||||
ret = AudioSystem::startInput(mInput);
|
ret = AudioSystem::startInput(mInput);
|
||||||
if (ret == NO_ERROR) {
|
if (ret == NO_ERROR) {
|
||||||
mNewPosition = mCblk->user + mUpdatePeriod;
|
|
||||||
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
|
|
||||||
mCblk->waitTimeMs = 0;
|
|
||||||
if (t != 0) {
|
|
||||||
t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
|
|
||||||
} else {
|
|
||||||
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
|
|
||||||
}
|
|
||||||
ret = mAudioRecord->start();
|
ret = mAudioRecord->start();
|
||||||
|
if (ret == DEAD_OBJECT) {
|
||||||
|
LOGV("start() dead IAudioRecord: creating a new one");
|
||||||
|
ret = openRecord(mCblk->sampleRate, mFormat, mChannelCount,
|
||||||
|
mFrameCount, mFlags);
|
||||||
|
}
|
||||||
|
if (ret == NO_ERROR) {
|
||||||
|
mNewPosition = mCblk->user + mUpdatePeriod;
|
||||||
|
mCblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
|
||||||
|
mCblk->waitTimeMs = 0;
|
||||||
|
if (t != 0) {
|
||||||
|
t->run("ClientRecordThread", THREAD_PRIORITY_AUDIO_CLIENT);
|
||||||
|
} else {
|
||||||
|
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGV("start() failed");
|
||||||
|
AudioSystem::stopInput(mInput);
|
||||||
|
android_atomic_and(~1, &mActive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -396,10 +390,48 @@ status_t AudioRecord::getPosition(uint32_t *position)
|
|||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
status_t AudioRecord::openRecord(
|
||||||
|
uint32_t sampleRate,
|
||||||
|
int format,
|
||||||
|
int channelCount,
|
||||||
|
int frameCount,
|
||||||
|
uint32_t flags)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
|
||||||
|
if (audioFlinger == 0) {
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp<IAudioRecord> record = audioFlinger->openRecord(getpid(), mInput,
|
||||||
|
sampleRate, format,
|
||||||
|
channelCount,
|
||||||
|
frameCount,
|
||||||
|
((uint16_t)flags) << 16,
|
||||||
|
&status);
|
||||||
|
if (record == 0) {
|
||||||
|
LOGE("AudioFlinger could not create record track, status: %d", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
sp<IMemory> cblk = record->getCblk();
|
||||||
|
if (cblk == 0) {
|
||||||
|
LOGE("Could not get control block");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
mAudioRecord.clear();
|
||||||
|
mAudioRecord = record;
|
||||||
|
mCblkMemory.clear();
|
||||||
|
mCblkMemory = cblk;
|
||||||
|
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
|
||||||
|
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
|
||||||
|
mCblk->out = 0;
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
||||||
{
|
{
|
||||||
int active;
|
int active;
|
||||||
int timeout = 0;
|
|
||||||
status_t result;
|
status_t result;
|
||||||
audio_track_cblk_t* cblk = mCblk;
|
audio_track_cblk_t* cblk = mCblk;
|
||||||
uint32_t framesReq = audioBuffer->frameCount;
|
uint32_t framesReq = audioBuffer->frameCount;
|
||||||
@ -411,25 +443,40 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
|||||||
uint32_t framesReady = cblk->framesReady();
|
uint32_t framesReady = cblk->framesReady();
|
||||||
|
|
||||||
if (framesReady == 0) {
|
if (framesReady == 0) {
|
||||||
Mutex::Autolock _l(cblk->lock);
|
cblk->lock.lock();
|
||||||
goto start_loop_here;
|
goto start_loop_here;
|
||||||
while (framesReady == 0) {
|
while (framesReady == 0) {
|
||||||
active = mActive;
|
active = mActive;
|
||||||
if (UNLIKELY(!active))
|
if (UNLIKELY(!active)) {
|
||||||
|
cblk->lock.unlock();
|
||||||
return NO_MORE_BUFFERS;
|
return NO_MORE_BUFFERS;
|
||||||
if (UNLIKELY(!waitCount))
|
}
|
||||||
|
if (UNLIKELY(!waitCount)) {
|
||||||
|
cblk->lock.unlock();
|
||||||
return WOULD_BLOCK;
|
return WOULD_BLOCK;
|
||||||
timeout = 0;
|
}
|
||||||
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
|
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
|
||||||
if (__builtin_expect(result!=NO_ERROR, false)) {
|
if (__builtin_expect(result!=NO_ERROR, false)) {
|
||||||
cblk->waitTimeMs += waitTimeMs;
|
cblk->waitTimeMs += waitTimeMs;
|
||||||
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
|
if (cblk->waitTimeMs >= cblk->bufferTimeoutMs) {
|
||||||
LOGW( "obtainBuffer timed out (is the CPU pegged?) "
|
LOGW( "obtainBuffer timed out (is the CPU pegged?) "
|
||||||
"user=%08x, server=%08x", cblk->user, cblk->server);
|
"user=%08x, server=%08x", cblk->user, cblk->server);
|
||||||
timeout = 1;
|
cblk->lock.unlock();
|
||||||
|
result = mAudioRecord->start();
|
||||||
|
if (result == DEAD_OBJECT) {
|
||||||
|
LOGW("obtainBuffer() dead IAudioRecord: creating a new one");
|
||||||
|
result = openRecord(cblk->sampleRate, mFormat, mChannelCount,
|
||||||
|
mFrameCount, mFlags);
|
||||||
|
if (result == NO_ERROR) {
|
||||||
|
cblk = mCblk;
|
||||||
|
cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cblk->lock.lock();
|
||||||
cblk->waitTimeMs = 0;
|
cblk->waitTimeMs = 0;
|
||||||
}
|
}
|
||||||
if (--waitCount == 0) {
|
if (--waitCount == 0) {
|
||||||
|
cblk->lock.unlock();
|
||||||
return TIMED_OUT;
|
return TIMED_OUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -437,13 +484,9 @@ status_t AudioRecord::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
|||||||
start_loop_here:
|
start_loop_here:
|
||||||
framesReady = cblk->framesReady();
|
framesReady = cblk->framesReady();
|
||||||
}
|
}
|
||||||
|
cblk->lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGW_IF(timeout,
|
|
||||||
"*** SERIOUS WARNING *** obtainBuffer() timed out "
|
|
||||||
"but didn't need to be locked. We recovered, but "
|
|
||||||
"this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
|
|
||||||
|
|
||||||
cblk->waitTimeMs = 0;
|
cblk->waitTimeMs = 0;
|
||||||
|
|
||||||
if (framesReq > framesReady) {
|
if (framesReq > framesReady) {
|
||||||
|
@ -122,11 +122,6 @@ status_t AudioTrack::set(
|
|||||||
return INVALID_OPERATION;
|
return INVALID_OPERATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
|
|
||||||
if (audioFlinger == 0) {
|
|
||||||
LOGE("Could not get audioflinger");
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
int afSampleRate;
|
int afSampleRate;
|
||||||
if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
|
if (AudioSystem::getOutputSamplingRate(&afSampleRate, streamType) != NO_ERROR) {
|
||||||
return NO_INIT;
|
return NO_INIT;
|
||||||
@ -217,28 +212,16 @@ status_t AudioTrack::set(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// create the track
|
mVolume[LEFT] = 1.0f;
|
||||||
status_t status;
|
mVolume[RIGHT] = 1.0f;
|
||||||
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
|
// create the IAudioTrack
|
||||||
streamType,
|
status_t status = createTrack(streamType, sampleRate, format, channelCount,
|
||||||
sampleRate,
|
frameCount, flags, sharedBuffer, output);
|
||||||
format,
|
|
||||||
channelCount,
|
|
||||||
frameCount,
|
|
||||||
((uint16_t)flags) << 16,
|
|
||||||
sharedBuffer,
|
|
||||||
output,
|
|
||||||
&status);
|
|
||||||
|
|
||||||
if (track == 0) {
|
if (status != NO_ERROR) {
|
||||||
LOGE("AudioFlinger could not create track, status: %d", status);
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
sp<IMemory> cblk = track->getCblk();
|
|
||||||
if (cblk == 0) {
|
|
||||||
LOGE("Could not get control block");
|
|
||||||
return NO_INIT;
|
|
||||||
}
|
|
||||||
if (cbf != 0) {
|
if (cbf != 0) {
|
||||||
mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
|
mAudioTrackThread = new AudioTrackThread(*this, threadCanCallJava);
|
||||||
if (mAudioTrackThread == 0) {
|
if (mAudioTrackThread == 0) {
|
||||||
@ -249,22 +232,6 @@ status_t AudioTrack::set(
|
|||||||
|
|
||||||
mStatus = NO_ERROR;
|
mStatus = NO_ERROR;
|
||||||
|
|
||||||
mAudioTrack = track;
|
|
||||||
mCblkMemory = cblk;
|
|
||||||
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
|
|
||||||
mCblk->out = 1;
|
|
||||||
// Update buffer size in case it has been limited by AudioFlinger during track creation
|
|
||||||
mFrameCount = mCblk->frameCount;
|
|
||||||
if (sharedBuffer == 0) {
|
|
||||||
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
|
|
||||||
} else {
|
|
||||||
mCblk->buffers = sharedBuffer->pointer();
|
|
||||||
// Force buffer full condition as data is already present in shared memory
|
|
||||||
mCblk->stepUser(mFrameCount);
|
|
||||||
}
|
|
||||||
mCblk->volume[0] = mCblk->volume[1] = 0x1000;
|
|
||||||
mVolume[LEFT] = 1.0f;
|
|
||||||
mVolume[RIGHT] = 1.0f;
|
|
||||||
mStreamType = streamType;
|
mStreamType = streamType;
|
||||||
mFormat = format;
|
mFormat = format;
|
||||||
mChannels = channels;
|
mChannels = channels;
|
||||||
@ -351,16 +318,27 @@ void AudioTrack::start()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (android_atomic_or(1, &mActive) == 0) {
|
if (android_atomic_or(1, &mActive) == 0) {
|
||||||
AudioSystem::startOutput(getOutput(), (AudioSystem::stream_type)mStreamType);
|
audio_io_handle_t output = AudioTrack::getOutput();
|
||||||
mNewPosition = mCblk->server + mUpdatePeriod;
|
status_t status = mAudioTrack->start();
|
||||||
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
|
if (status == DEAD_OBJECT) {
|
||||||
mCblk->waitTimeMs = 0;
|
LOGV("start() dead IAudioTrack: creating a new one");
|
||||||
if (t != 0) {
|
status = createTrack(mStreamType, mCblk->sampleRate, mFormat, mChannelCount,
|
||||||
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
|
mFrameCount, mFlags, mSharedBuffer, output);
|
||||||
} else {
|
}
|
||||||
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
|
if (status == NO_ERROR) {
|
||||||
|
AudioSystem::startOutput(output, (AudioSystem::stream_type)mStreamType);
|
||||||
|
mNewPosition = mCblk->server + mUpdatePeriod;
|
||||||
|
mCblk->bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS;
|
||||||
|
mCblk->waitTimeMs = 0;
|
||||||
|
if (t != 0) {
|
||||||
|
t->run("AudioTrackThread", THREAD_PRIORITY_AUDIO_CLIENT);
|
||||||
|
} else {
|
||||||
|
setpriority(PRIO_PROCESS, 0, THREAD_PRIORITY_AUDIO_CLIENT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOGV("start() failed");
|
||||||
|
android_atomic_and(~1, &mActive);
|
||||||
}
|
}
|
||||||
mAudioTrack->start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (t != 0) {
|
if (t != 0) {
|
||||||
@ -617,10 +595,67 @@ audio_io_handle_t AudioTrack::getOutput()
|
|||||||
|
|
||||||
// -------------------------------------------------------------------------
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
status_t AudioTrack::createTrack(
|
||||||
|
int streamType,
|
||||||
|
uint32_t sampleRate,
|
||||||
|
int format,
|
||||||
|
int channelCount,
|
||||||
|
int frameCount,
|
||||||
|
uint32_t flags,
|
||||||
|
const sp<IMemory>& sharedBuffer,
|
||||||
|
audio_io_handle_t output)
|
||||||
|
{
|
||||||
|
status_t status;
|
||||||
|
const sp<IAudioFlinger>& audioFlinger = AudioSystem::get_audio_flinger();
|
||||||
|
if (audioFlinger == 0) {
|
||||||
|
LOGE("Could not get audioflinger");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
sp<IAudioTrack> track = audioFlinger->createTrack(getpid(),
|
||||||
|
streamType,
|
||||||
|
sampleRate,
|
||||||
|
format,
|
||||||
|
channelCount,
|
||||||
|
frameCount,
|
||||||
|
((uint16_t)flags) << 16,
|
||||||
|
sharedBuffer,
|
||||||
|
output,
|
||||||
|
&status);
|
||||||
|
|
||||||
|
if (track == 0) {
|
||||||
|
LOGE("AudioFlinger could not create track, status: %d", status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
sp<IMemory> cblk = track->getCblk();
|
||||||
|
if (cblk == 0) {
|
||||||
|
LOGE("Could not get control block");
|
||||||
|
return NO_INIT;
|
||||||
|
}
|
||||||
|
mAudioTrack.clear();
|
||||||
|
mAudioTrack = track;
|
||||||
|
mCblkMemory.clear();
|
||||||
|
mCblkMemory = cblk;
|
||||||
|
mCblk = static_cast<audio_track_cblk_t*>(cblk->pointer());
|
||||||
|
mCblk->out = 1;
|
||||||
|
// Update buffer size in case it has been limited by AudioFlinger during track creation
|
||||||
|
mFrameCount = mCblk->frameCount;
|
||||||
|
if (sharedBuffer == 0) {
|
||||||
|
mCblk->buffers = (char*)mCblk + sizeof(audio_track_cblk_t);
|
||||||
|
} else {
|
||||||
|
mCblk->buffers = sharedBuffer->pointer();
|
||||||
|
// Force buffer full condition as data is already present in shared memory
|
||||||
|
mCblk->stepUser(mFrameCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
mCblk->volumeLR = (int32_t(int16_t(mVolume[LEFT] * 0x1000)) << 16) | int16_t(mVolume[RIGHT] * 0x1000);
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
||||||
{
|
{
|
||||||
int active;
|
int active;
|
||||||
int timeout = 0;
|
|
||||||
status_t result;
|
status_t result;
|
||||||
audio_track_cblk_t* cblk = mCblk;
|
audio_track_cblk_t* cblk = mCblk;
|
||||||
uint32_t framesReq = audioBuffer->frameCount;
|
uint32_t framesReq = audioBuffer->frameCount;
|
||||||
@ -632,17 +667,20 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
|||||||
uint32_t framesAvail = cblk->framesAvailable();
|
uint32_t framesAvail = cblk->framesAvailable();
|
||||||
|
|
||||||
if (framesAvail == 0) {
|
if (framesAvail == 0) {
|
||||||
Mutex::Autolock _l(cblk->lock);
|
cblk->lock.lock();
|
||||||
goto start_loop_here;
|
goto start_loop_here;
|
||||||
while (framesAvail == 0) {
|
while (framesAvail == 0) {
|
||||||
active = mActive;
|
active = mActive;
|
||||||
if (UNLIKELY(!active)) {
|
if (UNLIKELY(!active)) {
|
||||||
LOGV("Not active and NO_MORE_BUFFERS");
|
LOGV("Not active and NO_MORE_BUFFERS");
|
||||||
|
cblk->lock.unlock();
|
||||||
return NO_MORE_BUFFERS;
|
return NO_MORE_BUFFERS;
|
||||||
}
|
}
|
||||||
if (UNLIKELY(!waitCount))
|
if (UNLIKELY(!waitCount)) {
|
||||||
|
cblk->lock.unlock();
|
||||||
return WOULD_BLOCK;
|
return WOULD_BLOCK;
|
||||||
timeout = 0;
|
}
|
||||||
|
|
||||||
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
|
result = cblk->cv.waitRelative(cblk->lock, milliseconds(waitTimeMs));
|
||||||
if (__builtin_expect(result!=NO_ERROR, false)) {
|
if (__builtin_expect(result!=NO_ERROR, false)) {
|
||||||
cblk->waitTimeMs += waitTimeMs;
|
cblk->waitTimeMs += waitTimeMs;
|
||||||
@ -654,14 +692,23 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
|||||||
"user=%08x, server=%08x", this, cblk->user, cblk->server);
|
"user=%08x, server=%08x", this, cblk->user, cblk->server);
|
||||||
//unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
|
//unlock cblk mutex before calling mAudioTrack->start() (see issue #1617140)
|
||||||
cblk->lock.unlock();
|
cblk->lock.unlock();
|
||||||
mAudioTrack->start();
|
result = mAudioTrack->start();
|
||||||
|
if (result == DEAD_OBJECT) {
|
||||||
|
LOGW("obtainBuffer() dead IAudioTrack: creating a new one");
|
||||||
|
result = createTrack(mStreamType, cblk->sampleRate, mFormat, mChannelCount,
|
||||||
|
mFrameCount, mFlags, mSharedBuffer, getOutput());
|
||||||
|
if (result == NO_ERROR) {
|
||||||
|
cblk = mCblk;
|
||||||
|
cblk->bufferTimeoutMs = MAX_RUN_TIMEOUT_MS;
|
||||||
|
}
|
||||||
|
}
|
||||||
cblk->lock.lock();
|
cblk->lock.lock();
|
||||||
timeout = 1;
|
|
||||||
}
|
}
|
||||||
cblk->waitTimeMs = 0;
|
cblk->waitTimeMs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (--waitCount == 0) {
|
if (--waitCount == 0) {
|
||||||
|
cblk->lock.unlock();
|
||||||
return TIMED_OUT;
|
return TIMED_OUT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,6 +716,7 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
|||||||
start_loop_here:
|
start_loop_here:
|
||||||
framesAvail = cblk->framesAvailable_l();
|
framesAvail = cblk->framesAvailable_l();
|
||||||
}
|
}
|
||||||
|
cblk->lock.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
cblk->waitTimeMs = 0;
|
cblk->waitTimeMs = 0;
|
||||||
@ -684,11 +732,6 @@ status_t AudioTrack::obtainBuffer(Buffer* audioBuffer, int32_t waitCount)
|
|||||||
framesReq = bufferEnd - u;
|
framesReq = bufferEnd - u;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGW_IF(timeout,
|
|
||||||
"*** SERIOUS WARNING *** obtainBuffer() timed out "
|
|
||||||
"but didn't need to be locked. We recovered, but "
|
|
||||||
"this shouldn't happen (user=%08x, server=%08x)", cblk->user, cblk->server);
|
|
||||||
|
|
||||||
audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
|
audioBuffer->flags = mMuted ? Buffer::MUTE : 0;
|
||||||
audioBuffer->channelCount = mChannelCount;
|
audioBuffer->channelCount = mChannelCount;
|
||||||
audioBuffer->frameCount = framesReq;
|
audioBuffer->frameCount = framesReq;
|
||||||
@ -991,7 +1034,7 @@ bool audio_track_cblk_t::stepServer(uint32_t frameCount)
|
|||||||
// Mark that we have read the first buffer so that next time stepUser() is called
|
// Mark that we have read the first buffer so that next time stepUser() is called
|
||||||
// we switch to normal obtainBuffer() timeout period
|
// we switch to normal obtainBuffer() timeout period
|
||||||
if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
|
if (bufferTimeoutMs == MAX_STARTUP_TIMEOUT_MS) {
|
||||||
bufferTimeoutMs = MAX_RUN_TIMEOUT_MS - 1;
|
bufferTimeoutMs = MAX_STARTUP_TIMEOUT_MS - 1;
|
||||||
}
|
}
|
||||||
// It is possible that we receive a flush()
|
// It is possible that we receive a flush()
|
||||||
// while the mixer is processing a block: in this case,
|
// while the mixer is processing a block: in this case,
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "IAudioRecord"
|
||||||
|
//#define LOG_NDEBUG 0
|
||||||
|
#include <utils/Log.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@ -42,8 +46,13 @@ public:
|
|||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
|
data.writeInterfaceToken(IAudioRecord::getInterfaceDescriptor());
|
||||||
remote()->transact(START, data, &reply);
|
status_t status = remote()->transact(START, data, &reply);
|
||||||
return reply.readInt32();
|
if (status == NO_ERROR) {
|
||||||
|
status = reply.readInt32();
|
||||||
|
} else {
|
||||||
|
LOGW("start() error: %s", strerror(-status));
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void stop()
|
virtual void stop()
|
||||||
|
@ -15,6 +15,10 @@
|
|||||||
** limitations under the License.
|
** limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define LOG_TAG "IAudioTrack"
|
||||||
|
//#define LOG_NDEBUG 0
|
||||||
|
#include <utils/Log.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
@ -45,8 +49,13 @@ public:
|
|||||||
{
|
{
|
||||||
Parcel data, reply;
|
Parcel data, reply;
|
||||||
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
|
data.writeInterfaceToken(IAudioTrack::getInterfaceDescriptor());
|
||||||
remote()->transact(START, data, &reply);
|
status_t status = remote()->transact(START, data, &reply);
|
||||||
return reply.readInt32();
|
if (status == NO_ERROR) {
|
||||||
|
status = reply.readInt32();
|
||||||
|
} else {
|
||||||
|
LOGW("start() error: %s", strerror(-status));
|
||||||
|
}
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void stop()
|
virtual void stop()
|
||||||
|
@ -798,7 +798,7 @@ const unsigned char ToneGenerator::sToneMappingTable[NUM_REGIONS-1][NUM_SUP_TONE
|
|||||||
// none
|
// none
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
ToneGenerator::ToneGenerator(int streamType, float volume) {
|
ToneGenerator::ToneGenerator(int streamType, float volume, bool threadCanCallJava) {
|
||||||
|
|
||||||
LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume);
|
LOGV("ToneGenerator constructor: streamType=%d, volume=%f\n", streamType, volume);
|
||||||
|
|
||||||
@ -808,6 +808,7 @@ ToneGenerator::ToneGenerator(int streamType, float volume) {
|
|||||||
LOGE("Unable to marshal AudioFlinger");
|
LOGE("Unable to marshal AudioFlinger");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
mThreadCanCallJava = threadCanCallJava;
|
||||||
mStreamType = streamType;
|
mStreamType = streamType;
|
||||||
mVolume = volume;
|
mVolume = volume;
|
||||||
mpAudioTrack = 0;
|
mpAudioTrack = 0;
|
||||||
@ -1015,15 +1016,25 @@ bool ToneGenerator::initAudioTrack() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
|
// Open audio track in mono, PCM 16bit, default sampling rate, default buffer size
|
||||||
mpAudioTrack
|
mpAudioTrack = new AudioTrack();
|
||||||
= new AudioTrack(mStreamType, 0, AudioSystem::PCM_16_BIT, AudioSystem::CHANNEL_OUT_MONO, 0, 0, audioCallback, this, 0);
|
|
||||||
|
|
||||||
if (mpAudioTrack == 0) {
|
if (mpAudioTrack == 0) {
|
||||||
LOGE("AudioTrack allocation failed");
|
LOGE("AudioTrack allocation failed");
|
||||||
goto initAudioTrack_exit;
|
goto initAudioTrack_exit;
|
||||||
}
|
}
|
||||||
LOGV("Create Track: %p\n", mpAudioTrack);
|
LOGV("Create Track: %p\n", mpAudioTrack);
|
||||||
|
|
||||||
|
mpAudioTrack->set(mStreamType,
|
||||||
|
0,
|
||||||
|
AudioSystem::PCM_16_BIT,
|
||||||
|
AudioSystem::CHANNEL_OUT_MONO,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
audioCallback,
|
||||||
|
this,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
mThreadCanCallJava);
|
||||||
|
|
||||||
if (mpAudioTrack->initCheck() != NO_ERROR) {
|
if (mpAudioTrack->initCheck() != NO_ERROR) {
|
||||||
LOGE("AudioTrack->initCheck failed");
|
LOGE("AudioTrack->initCheck failed");
|
||||||
goto initAudioTrack_exit;
|
goto initAudioTrack_exit;
|
||||||
|
Reference in New Issue
Block a user