NBAIO: re-implement NBAIO Pipe and MonoPipe using fifo
Also removed const from NBAIO_Sink::availableToWrite() because
at least one implementation can no longer implement the const-ness.
Test: normal mixer, tee sink, and remote submix still work
Change-Id: I8461177efdf53bba8295b147e97835b018804903
diff --git a/media/libnbaio/PipeReader.cpp b/media/libnbaio/PipeReader.cpp
index fdea68e..bd468a6 100644
--- a/media/libnbaio/PipeReader.cpp
+++ b/media/libnbaio/PipeReader.cpp
@@ -25,9 +25,7 @@
PipeReader::PipeReader(Pipe& pipe) :
NBAIO_Source(pipe.mFormat),
- mPipe(pipe),
- // any data already in the pipe is not visible to this PipeReader
- mFront(android_atomic_acquire_load(&pipe.mRear)),
+ mPipe(pipe), mFifoReader(mPipe.mFifo, false /*throttlesWriter*/),
mFramesOverrun(0),
mOverruns(0)
{
@@ -45,71 +43,54 @@
ALOG_ASSERT(readers > 0);
}
-__attribute__((no_sanitize("integer")))
ssize_t PipeReader::availableToRead()
{
if (CC_UNLIKELY(!mNegotiated)) {
return NEGOTIATE;
}
- int32_t rear = android_atomic_acquire_load(&mPipe.mRear);
- // read() is not multi-thread safe w.r.t. itself, so no mutex or atomic op needed to read mFront
- size_t avail = rear - mFront;
- if (CC_UNLIKELY(avail > mPipe.mMaxFrames)) {
- // Discard all data in pipe to avoid another overrun immediately
- mFront = rear;
- mFramesOverrun += avail;
+ size_t lost;
+ ssize_t avail = mFifoReader.available(&lost);
+ if (avail == -EOVERFLOW || lost > 0) {
+ mFramesOverrun += lost;
++mOverruns;
- return OVERRUN;
+ avail = OVERRUN;
}
return avail;
}
-__attribute__((no_sanitize("integer")))
ssize_t PipeReader::read(void *buffer, size_t count)
{
- ssize_t avail = availableToRead();
- if (CC_UNLIKELY(avail <= 0)) {
- return avail;
+ size_t lost;
+ ssize_t actual = mFifoReader.read(buffer, count, NULL /*timeout*/, &lost);
+ ALOG_ASSERT(actual <= count);
+ if (actual == -EOVERFLOW || lost > 0) {
+ mFramesOverrun += lost;
+ ++mOverruns;
+ actual = OVERRUN;
}
- // An overrun can occur from here on and be silently ignored,
- // but it will be caught at next read()
- if (CC_LIKELY(count > (size_t) avail)) {
- count = avail;
+ if (actual <= 0) {
+ return actual;
}
- size_t front = mFront & (mPipe.mMaxFrames - 1);
- size_t red = mPipe.mMaxFrames - front;
- if (CC_LIKELY(red > count)) {
- red = count;
- }
- // In particular, an overrun during the memcpy will result in reading corrupt data
- memcpy(buffer, (char *) mPipe.mBuffer + (front * mFrameSize), red * mFrameSize);
- // We could re-read the rear pointer here to detect the corruption, but why bother?
- if (CC_UNLIKELY(front + red == mPipe.mMaxFrames)) {
- if (CC_UNLIKELY((count -= red) > front)) {
- count = front;
- }
- if (CC_LIKELY(count > 0)) {
- memcpy((char *) buffer + (red * mFrameSize), mPipe.mBuffer, count * mFrameSize);
- red += count;
- }
- }
- mFront += red;
- mFramesRead += red;
- return red;
+ mFramesRead += (size_t) actual;
+ return actual;
}
-__attribute__((no_sanitize("integer")))
ssize_t PipeReader::flush()
{
if (CC_UNLIKELY(!mNegotiated)) {
return NEGOTIATE;
}
- const int32_t rear = android_atomic_acquire_load(&mPipe.mRear);
- const size_t flushed = rear - mFront;
- // We don't check if flushed > mPipe.mMaxFrames (an overrun occurred) as the
- // distinction is unimportant; all data is dropped.
- mFront = rear;
- mFramesRead += flushed; // we consider flushed frames as read.
+ size_t lost;
+ ssize_t flushed = mFifoReader.flush(&lost);
+ if (flushed == -EOVERFLOW || lost > 0) {
+ mFramesOverrun += lost;
+ ++mOverruns;
+ flushed = OVERRUN;
+ }
+ if (flushed <= 0) {
+ return flushed;
+ }
+ mFramesRead += (size_t) flushed; // we consider flushed frames as read, but not lost frames
return flushed;
}