summaryrefslogtreecommitdiffstats
path: root/include/private/media
diff options
context:
space:
mode:
Diffstat (limited to 'include/private/media')
-rw-r--r--include/private/media/AudioTrackShared.h228
1 files changed, 183 insertions, 45 deletions
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 48b6b21..41e20f8 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <utils/threads.h>
+#include <utils/Log.h>
namespace android {
@@ -38,9 +39,26 @@ namespace android {
#define CBLK_INVALID 0x04 // track buffer invalidated by AudioFlinger, need to re-create
#define CBLK_DISABLED 0x08 // track disabled by AudioFlinger due to underrun, need to re-start
+struct AudioTrackSharedStreaming {
+ // similar to NBAIO MonoPipe
+ volatile int32_t mFront;
+ volatile int32_t mRear;
+};
+
+// future
+struct AudioTrackSharedStatic {
+ int mReserved;
+};
+
+// ----------------------------------------------------------------------------
+
// Important: do not add any virtual methods, including ~
struct audio_track_cblk_t
{
+ friend class Proxy;
+ friend class AudioTrackClientProxy;
+ friend class AudioRecordClientProxy;
+ friend class ServerProxy;
// The data members are grouped so that members accessed frequently and in the same context
// are in the same line of data cache.
@@ -72,12 +90,13 @@ struct audio_track_cblk_t
// For AudioTrack only, not used by AudioRecord.
private:
uint32_t mVolumeLR;
-public:
- uint32_t sampleRate;
+ uint32_t mSampleRate; // AudioTrack only: client's requested sample rate in Hz
+ // or 0 == default. Write-only client, read-only server.
uint8_t mPad2; // unused
+public:
// read-only for client, server writes once at initialization and is then read-only
uint8_t mName; // normal tracks: track name, fast tracks: track index
@@ -94,65 +113,184 @@ public:
// Cache line boundary (32 bytes)
+#if 0
+ union {
+ AudioTrackSharedStreaming mStreaming;
+ AudioTrackSharedStatic mStatic;
+ int mAlign[8];
+ } u;
+
+ // Cache line boundary (32 bytes)
+#endif
+
// Since the control block is always located in shared memory, this constructor
// is only used for placement new(). It is never used for regular new() or stack.
audio_track_cblk_t();
- // called by client only, where client includes regular
- // AudioTrack and AudioFlinger::PlaybackThread::OutputTrack
- uint32_t stepUserIn(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, false); }
- uint32_t stepUserOut(size_t stepCount, size_t frameCount) { return stepUser(stepCount, frameCount, true); }
-
- bool stepServer(size_t stepCount, size_t frameCount, bool isOut);
-
+private:
// if there is a shared buffer, "buffers" is the value of pointer() for the shared
// buffer, otherwise "buffers" points immediately after the control block
- void* buffer(void *buffers, uint32_t frameSize, uint32_t offset) const;
-
- uint32_t framesAvailableIn(size_t frameCount)
- { return framesAvailable(frameCount, false); }
- uint32_t framesAvailableOut(size_t frameCount)
- { return framesAvailable(frameCount, true); }
- uint32_t framesAvailableIn_l(size_t frameCount)
- { return framesAvailable_l(frameCount, false); }
- uint32_t framesAvailableOut_l(size_t frameCount)
- { return framesAvailable_l(frameCount, true); }
- uint32_t framesReadyIn() { return framesReady(false); }
- uint32_t framesReadyOut() { return framesReady(true); }
+ void* buffer(void *buffers, uint32_t frameSize, size_t offset) const;
bool tryLock();
- // No barriers on the following operations, so the ordering of loads/stores
- // with respect to other parameters is UNPREDICTABLE. That's considered safe.
-
- // for AudioTrack client only, caller must limit to 0.0 <= sendLevel <= 1.0
- void setSendLevel(float sendLevel) {
- mSendLevel = uint16_t(sendLevel * 0x1000);
- }
-
- // for AudioFlinger only; the return value must be validated by the caller
- uint16_t getSendLevel_U4_12() const {
- return mSendLevel;
- }
-
- // for AudioTrack client only, caller must limit to 0 <= volumeLR <= 0x10001000
- void setVolumeLR(uint32_t volumeLR) {
- mVolumeLR = volumeLR;
- }
-
- // for AudioFlinger only; the return value must be validated by the caller
- uint32_t getVolumeLR() const {
- return mVolumeLR;
- }
-
-private:
// isOut == true means AudioTrack, isOut == false means AudioRecord
+ bool stepServer(size_t stepCount, size_t frameCount, bool isOut);
uint32_t stepUser(size_t stepCount, size_t frameCount, bool isOut);
uint32_t framesAvailable(size_t frameCount, bool isOut);
uint32_t framesAvailable_l(size_t frameCount, bool isOut);
uint32_t framesReady(bool isOut);
};
+// ----------------------------------------------------------------------------
+
+// Proxy for shared memory control block, to isolate callers from needing to know the details.
+// There is exactly one ClientProxy and one ServerProxy per shared memory control block.
+// The proxies are located in normal memory, and are not multi-thread safe within a given side.
+class Proxy {
+protected:
+ Proxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
+ : mCblk(cblk), mBuffers(buffers), mFrameCount(frameCount), mFrameSize(frameSize) { }
+ virtual ~Proxy() { }
+
+public:
+ void* buffer(size_t offset) const {
+ return mCblk->buffer(mBuffers, mFrameSize, offset);
+ }
+
+protected:
+ // These refer to shared memory, and are virtual addresses with respect to the current process.
+ // They may have different virtual addresses within the other process.
+ audio_track_cblk_t* const mCblk; // the control block
+ void* const mBuffers; // starting address of buffers
+
+ const size_t mFrameCount; // not necessarily a power of 2
+ const size_t mFrameSize; // in bytes
+#if 0
+ const size_t mFrameCountP2; // mFrameCount rounded to power of 2, streaming mode
+#endif
+
+};
+
+// ----------------------------------------------------------------------------
+
+// Proxy seen by AudioTrack client and AudioRecord client
+class ClientProxy : public Proxy {
+protected:
+ ClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
+ : Proxy(cblk, buffers, frameCount, frameSize) { }
+ virtual ~ClientProxy() { }
+};
+
+// ----------------------------------------------------------------------------
+
+// Proxy used by AudioTrack client, which also includes AudioFlinger::PlaybackThread::OutputTrack
+class AudioTrackClientProxy : public ClientProxy {
+public:
+ AudioTrackClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
+ : ClientProxy(cblk, buffers, frameCount, frameSize) { }
+ virtual ~AudioTrackClientProxy() { }
+
+ // No barriers on the following operations, so the ordering of loads/stores
+ // with respect to other parameters is UNPREDICTABLE. That's considered safe.
+
+ // caller must limit to 0.0 <= sendLevel <= 1.0
+ void setSendLevel(float sendLevel) {
+ mCblk->mSendLevel = uint16_t(sendLevel * 0x1000);
+ }
+
+ // caller must limit to 0 <= volumeLR <= 0x10001000
+ void setVolumeLR(uint32_t volumeLR) {
+ mCblk->mVolumeLR = volumeLR;
+ }
+
+ void setSampleRate(uint32_t sampleRate) {
+ mCblk->mSampleRate = sampleRate;
+ }
+
+ // called by:
+ // PlaybackThread::OutputTrack::write
+ // AudioTrack::createTrack_l
+ // AudioTrack::releaseBuffer
+ // AudioTrack::reload
+ // AudioTrack::restoreTrack_l (2 places)
+ size_t stepUser(size_t stepCount) {
+ return mCblk->stepUser(stepCount, mFrameCount, true /*isOut*/);
+ }
+
+ // called by AudioTrack::obtainBuffer and AudioTrack::processBuffer
+ size_t framesAvailable() {
+ return mCblk->framesAvailable(mFrameCount, true /*isOut*/);
+ }
+
+ // called by AudioTrack::obtainBuffer and PlaybackThread::OutputTrack::obtainBuffer
+ // FIXME remove this API since it assumes a lock that should be invisible to caller
+ size_t framesAvailable_l() {
+ return mCblk->framesAvailable_l(mFrameCount, true /*isOut*/);
+ }
+
+};
+
+// ----------------------------------------------------------------------------
+
+// Proxy used by AudioRecord client
+class AudioRecordClientProxy : public ClientProxy {
+public:
+ AudioRecordClientProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize)
+ : ClientProxy(cblk, buffers, frameCount, frameSize) { }
+ ~AudioRecordClientProxy() { }
+
+ // called by AudioRecord::releaseBuffer
+ size_t stepUser(size_t stepCount) {
+ return mCblk->stepUser(stepCount, mFrameCount, false /*isOut*/);
+ }
+
+ // called by AudioRecord::processBuffer
+ size_t framesAvailable() {
+ return mCblk->framesAvailable(mFrameCount, false /*isOut*/);
+ }
+
+ // called by AudioRecord::obtainBuffer
+ size_t framesReady() {
+ return mCblk->framesReady(false /*isOut*/);
+ }
+
+};
+
+// ----------------------------------------------------------------------------
+
+// Proxy used by AudioFlinger server
+class ServerProxy : public Proxy {
+public:
+ ServerProxy(audio_track_cblk_t* cblk, void *buffers, size_t frameCount, size_t frameSize, bool isOut)
+ : Proxy(cblk, buffers, frameCount, frameSize), mIsOut(isOut) { }
+ virtual ~ServerProxy() { }
+
+ // for AudioTrack and AudioRecord
+ bool step(size_t stepCount) { return mCblk->stepServer(stepCount, mFrameCount, mIsOut); }
+
+ // return value of these methods must be validated by the caller
+ uint32_t getSampleRate() const { return mCblk->mSampleRate; }
+ uint16_t getSendLevel_U4_12() const { return mCblk->mSendLevel; }
+ uint32_t getVolumeLR() const { return mCblk->mVolumeLR; }
+
+ // for AudioTrack only
+ size_t framesReady() {
+ ALOG_ASSERT(mIsOut);
+ return mCblk->framesReady(true);
+ }
+
+ // for AudioRecord only, called by RecordThread::RecordTrack::getNextBuffer
+ // FIXME remove this API since it assumes a lock that should be invisible to caller
+ size_t framesAvailableIn_l() {
+ ALOG_ASSERT(!mIsOut);
+ return mCblk->framesAvailable_l(mFrameCount, false);
+ }
+
+private:
+ const bool mIsOut; // true for AudioTrack, false for AudioRecord
+
+};
// ----------------------------------------------------------------------------