summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGlenn Kasten <gkasten@google.com>2014-03-13 14:59:31 -0700
committerGlenn Kasten <gkasten@google.com>2014-05-22 16:19:08 -0700
commitf91df1b368a140abd37c80b204bd48d78778cc43 (patch)
tree238d896ad29af48d8ee069e853ee9fa1035955cc
parent29b703eec27b305e7b5b2343bf257643e38f6b68 (diff)
downloadframeworks_av-f91df1b368a140abd37c80b204bd48d78778cc43.zip
frameworks_av-f91df1b368a140abd37c80b204bd48d78778cc43.tar.gz
frameworks_av-f91df1b368a140abd37c80b204bd48d78778cc43.tar.bz2
Start adding FastCapture based on FastThread WIP
This version supports at most one fast capture client. Change-Id: Idf609bfc80ae22433433d66a5232c043c65506df
-rw-r--r--services/audioflinger/Android.mk1
-rw-r--r--services/audioflinger/FastCapture.cpp222
-rw-r--r--services/audioflinger/FastCapture.h78
-rw-r--r--services/audioflinger/FastCaptureState.cpp30
-rw-r--r--services/audioflinger/FastCaptureState.h51
-rw-r--r--services/audioflinger/StateQueueInstantiations.cpp4
6 files changed, 385 insertions, 1 deletions
diff --git a/services/audioflinger/Android.mk b/services/audioflinger/Android.mk
index 8d0a705..3b128cf 100644
--- a/services/audioflinger/Android.mk
+++ b/services/audioflinger/Android.mk
@@ -63,6 +63,7 @@ LOCAL_32_BIT_ONLY := true
LOCAL_SRC_FILES += FastMixer.cpp FastMixerState.cpp AudioWatchdog.cpp
LOCAL_SRC_FILES += FastThread.cpp FastThreadState.cpp
+LOCAL_SRC_FILES += FastCapture.cpp FastCaptureState.cpp
LOCAL_CFLAGS += -DSTATE_QUEUE_INSTANTIATIONS='"StateQueueInstantiations.cpp"'
diff --git a/services/audioflinger/FastCapture.cpp b/services/audioflinger/FastCapture.cpp
new file mode 100644
index 0000000..0c9b976
--- /dev/null
+++ b/services/audioflinger/FastCapture.cpp
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "FastCapture"
+//#define LOG_NDEBUG 0
+
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+
+#include "Configuration.h"
+#include <linux/futex.h>
+#include <sys/syscall.h>
+#include <media/AudioBufferProvider.h>
+#include <utils/Log.h>
+#include <utils/Trace.h>
+#include "FastCapture.h"
+
+namespace android {
+
+/*static*/ const FastCaptureState FastCapture::initial;
+
+FastCapture::FastCapture() : FastThread(),
+ inputSource(NULL), inputSourceGen(0), pipeSink(NULL), pipeSinkGen(0),
+ readBuffer(NULL), readBufferState(-1), format(Format_Invalid), sampleRate(0),
+ // dummyDumpState
+ totalNativeFramesRead(0)
+{
+ previous = &initial;
+ current = &initial;
+
+ mDummyDumpState = &dummyDumpState;
+}
+
+FastCapture::~FastCapture()
+{
+}
+
+FastCaptureStateQueue* FastCapture::sq()
+{
+ return &mSQ;
+}
+
+const FastThreadState *FastCapture::poll()
+{
+ return mSQ.poll();
+}
+
+void FastCapture::setLog(NBLog::Writer *logWriter __unused)
+{
+}
+
+void FastCapture::onIdle()
+{
+ preIdle = *(const FastCaptureState *)current;
+ current = &preIdle;
+}
+
+void FastCapture::onExit()
+{
+ delete[] readBuffer;
+}
+
+bool FastCapture::isSubClassCommand(FastThreadState::Command command)
+{
+ switch ((FastCaptureState::Command) command) {
+ case FastCaptureState::READ:
+ case FastCaptureState::WRITE:
+ case FastCaptureState::READ_WRITE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void FastCapture::onStateChange()
+{
+ const FastCaptureState * const current = (const FastCaptureState *) this->current;
+ const FastCaptureState * const previous = (const FastCaptureState *) this->previous;
+ FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
+ const size_t frameCount = current->mFrameCount;
+
+ bool eitherChanged = false;
+
+ // check for change in input HAL configuration
+ NBAIO_Format previousFormat = format;
+ if (current->mInputSourceGen != inputSourceGen) {
+ inputSource = current->mInputSource;
+ inputSourceGen = current->mInputSourceGen;
+ if (inputSource == NULL) {
+ format = Format_Invalid;
+ sampleRate = 0;
+ } else {
+ format = inputSource->format();
+ sampleRate = Format_sampleRate(format);
+ unsigned channelCount = Format_channelCount(format);
+ ALOG_ASSERT(channelCount == 1 || channelCount == 2);
+ }
+ dumpState->mSampleRate = sampleRate;
+ eitherChanged = true;
+ }
+
+ // check for change in pipe
+ if (current->mPipeSinkGen != pipeSinkGen) {
+ pipeSink = current->mPipeSink;
+ pipeSinkGen = current->mPipeSinkGen;
+ eitherChanged = true;
+ }
+
+ // input source and pipe sink must be compatible
+ if (eitherChanged && inputSource != NULL && pipeSink != NULL) {
+ ALOG_ASSERT(Format_isEqual(format, pipeSink->format()));
+ }
+
+ if ((!Format_isEqual(format, previousFormat)) || (frameCount != previous->mFrameCount)) {
+ // FIXME to avoid priority inversion, don't delete here
+ delete[] readBuffer;
+ readBuffer = NULL;
+ if (frameCount > 0 && sampleRate > 0) {
+ // FIXME new may block for unbounded time at internal mutex of the heap
+ // implementation; it would be better to have normal capture thread allocate for
+ // us to avoid blocking here and to prevent possible priority inversion
+ unsigned channelCount = Format_channelCount(format);
+ // FIXME frameSize
+ readBuffer = new short[frameCount * channelCount];
+ periodNs = (frameCount * 1000000000LL) / sampleRate; // 1.00
+ underrunNs = (frameCount * 1750000000LL) / sampleRate; // 1.75
+ overrunNs = (frameCount * 500000000LL) / sampleRate; // 0.50
+ forceNs = (frameCount * 950000000LL) / sampleRate; // 0.95
+ warmupNs = (frameCount * 500000000LL) / sampleRate; // 0.50
+ } else {
+ periodNs = 0;
+ underrunNs = 0;
+ overrunNs = 0;
+ forceNs = 0;
+ warmupNs = 0;
+ }
+ readBufferState = -1;
+ dumpState->mFrameCount = frameCount;
+ }
+
+}
+
+void FastCapture::onWork()
+{
+ const FastCaptureState * const current = (const FastCaptureState *) this->current;
+ FastCaptureDumpState * const dumpState = (FastCaptureDumpState *) this->dumpState;
+ const FastCaptureState::Command command = this->command;
+ const size_t frameCount = current->mFrameCount;
+
+ if ((command & FastCaptureState::READ) /*&& isWarm*/) {
+ ALOG_ASSERT(inputSource != NULL);
+ ALOG_ASSERT(readBuffer != NULL);
+ dumpState->mReadSequence++;
+ ATRACE_BEGIN("read");
+ ssize_t framesRead = inputSource->read(readBuffer, frameCount,
+ AudioBufferProvider::kInvalidPTS);
+ ATRACE_END();
+ dumpState->mReadSequence++;
+ if (framesRead >= 0) {
+ LOG_ALWAYS_FATAL_IF((size_t) framesRead > frameCount);
+ totalNativeFramesRead += framesRead;
+ dumpState->mFramesRead = totalNativeFramesRead;
+ readBufferState = framesRead;
+ } else {
+ dumpState->mReadErrors++;
+ readBufferState = 0;
+ }
+ // FIXME rename to attemptedIO
+ attemptedWrite = true;
+ }
+
+ if (command & FastCaptureState::WRITE) {
+ ALOG_ASSERT(pipeSink != NULL);
+ ALOG_ASSERT(readBuffer != NULL);
+ if (readBufferState < 0) {
+ unsigned channelCount = Format_channelCount(format);
+ // FIXME frameSize
+ memset(readBuffer, 0, frameCount * channelCount * sizeof(short));
+ readBufferState = frameCount;
+ }
+ if (readBufferState > 0) {
+ ssize_t framesWritten = pipeSink->write(readBuffer, readBufferState);
+ // FIXME This supports at most one fast capture client.
+ // To handle multiple clients this could be converted to an array,
+ // or with a lot more work the control block could be shared by all clients.
+ audio_track_cblk_t* cblk = current->mCblk;
+ if (cblk != NULL && framesWritten > 0) {
+ int32_t rear = cblk->u.mStreaming.mRear;
+ android_atomic_release_store(framesWritten + rear, &cblk->u.mStreaming.mRear);
+ cblk->mServer += framesWritten;
+ int32_t old = android_atomic_or(CBLK_FUTEX_WAKE, &cblk->mFutex);
+ if (!(old & CBLK_FUTEX_WAKE)) {
+ // client is never in server process, so don't use FUTEX_WAKE_PRIVATE
+ (void) syscall(__NR_futex, &cblk->mFutex, FUTEX_WAKE, 1);
+ }
+ }
+ }
+ }
+}
+
+FastCaptureDumpState::FastCaptureDumpState() : FastThreadDumpState(),
+ mReadSequence(0), mFramesRead(0), mReadErrors(0), mSampleRate(0), mFrameCount(0)
+{
+}
+
+FastCaptureDumpState::~FastCaptureDumpState()
+{
+}
+
+} // namespace android
diff --git a/services/audioflinger/FastCapture.h b/services/audioflinger/FastCapture.h
new file mode 100644
index 0000000..e535b9d
--- /dev/null
+++ b/services/audioflinger/FastCapture.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_FAST_CAPTURE_H
+#define ANDROID_AUDIO_FAST_CAPTURE_H
+
+#include "FastThread.h"
+#include "StateQueue.h"
+#include "FastCaptureState.h"
+
+namespace android {
+
+typedef StateQueue<FastCaptureState> FastCaptureStateQueue;
+
+struct FastCaptureDumpState : FastThreadDumpState {
+ FastCaptureDumpState();
+ /*virtual*/ ~FastCaptureDumpState();
+
+ // FIXME by renaming, could pull up many of these to FastThreadDumpState
+ uint32_t mReadSequence; // incremented before and after each read()
+ uint32_t mFramesRead; // total number of frames read successfully
+ uint32_t mReadErrors; // total number of read() errors
+ uint32_t mSampleRate;
+ size_t mFrameCount;
+};
+
+class FastCapture : public FastThread {
+
+public:
+ FastCapture();
+ virtual ~FastCapture();
+
+ FastCaptureStateQueue* sq();
+
+private:
+ FastCaptureStateQueue mSQ;
+
+ // callouts
+ virtual const FastThreadState *poll();
+ virtual void setLog(NBLog::Writer *logWriter);
+ virtual void onIdle();
+ virtual void onExit();
+ virtual bool isSubClassCommand(FastThreadState::Command command);
+ virtual void onStateChange();
+ virtual void onWork();
+
+ static const FastCaptureState initial;
+ FastCaptureState preIdle; // copy of state before we went into idle
+ // FIXME by renaming, could pull up many of these to FastThread
+ NBAIO_Source *inputSource;
+ int inputSourceGen;
+ NBAIO_Sink *pipeSink;
+ int pipeSinkGen;
+ short *readBuffer;
+ ssize_t readBufferState; // number of initialized frames in readBuffer, or -1 to clear
+ NBAIO_Format format;
+ unsigned sampleRate;
+ FastCaptureDumpState dummyDumpState;
+ uint32_t totalNativeFramesRead; // copied to dumpState->mFramesRead
+
+}; // class FastCapture
+
+} // namespace android
+
+#endif // ANDROID_AUDIO_FAST_CAPTURE_H
diff --git a/services/audioflinger/FastCaptureState.cpp b/services/audioflinger/FastCaptureState.cpp
new file mode 100644
index 0000000..1d029b7
--- /dev/null
+++ b/services/audioflinger/FastCaptureState.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "FastCaptureState.h"
+
+namespace android {
+
+FastCaptureState::FastCaptureState() : FastThreadState(),
+ mInputSource(NULL), mInputSourceGen(0), mPipeSink(NULL), mPipeSinkGen(0), mFrameCount(0)
+{
+}
+
+FastCaptureState::~FastCaptureState()
+{
+}
+
+} // android
diff --git a/services/audioflinger/FastCaptureState.h b/services/audioflinger/FastCaptureState.h
new file mode 100644
index 0000000..29c865a
--- /dev/null
+++ b/services/audioflinger/FastCaptureState.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+#define ANDROID_AUDIO_FAST_CAPTURE_STATE_H
+
+#include <media/nbaio/NBAIO.h>
+#include "FastThreadState.h"
+#include <private/media/AudioTrackShared.h>
+
+namespace android {
+
+// Represent a single state of the fast capture
+struct FastCaptureState : FastThreadState {
+ FastCaptureState();
+ /*virtual*/ ~FastCaptureState();
+
+ // all pointer fields use raw pointers; objects are owned and ref-counted by RecordThread
+ NBAIO_Source *mInputSource; // HAL input device, must already be negotiated
+ // FIXME by renaming, could pull up these fields to FastThreadState
+ int mInputSourceGen; // increment when mInputSource is assigned
+ NBAIO_Sink *mPipeSink; // after reading from input source, write to this pipe sink
+ int mPipeSinkGen; // increment when mPipeSink is assigned
+ size_t mFrameCount; // number of frames per fast capture buffer
+ audio_track_cblk_t *mCblk; // control block for the single fast client, or NULL
+
+ // Extends FastThreadState::Command
+ static const Command
+ // The following commands also process configuration changes, and can be "or"ed:
+ READ = 0x8, // read from input source
+ WRITE = 0x10, // write to pipe sink
+ READ_WRITE = 0x18; // read from input source and write to pipe sink
+
+}; // struct FastCaptureState
+
+} // namespace android
+
+#endif // ANDROID_AUDIO_FAST_CAPTURE_STATE_H
diff --git a/services/audioflinger/StateQueueInstantiations.cpp b/services/audioflinger/StateQueueInstantiations.cpp
index 0d5cd0c..6f4505e 100644
--- a/services/audioflinger/StateQueueInstantiations.cpp
+++ b/services/audioflinger/StateQueueInstantiations.cpp
@@ -16,12 +16,14 @@
#include "Configuration.h"
#include "FastMixerState.h"
+#include "FastCaptureState.h"
#include "StateQueue.h"
// FIXME hack for gcc
namespace android {
-template class StateQueue<FastMixerState>; // typedef FastMixerStateQueue
+template class StateQueue<FastMixerState>; // typedef FastMixerStateQueue
+template class StateQueue<FastCaptureState>; // typedef FastCaptureStateQueue
}