1010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten/*
2010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Copyright (C) 2012 The Android Open Source Project
3010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten *
4010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Licensed under the Apache License, Version 2.0 (the "License");
5010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * you may not use this file except in compliance with the License.
6010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * You may obtain a copy of the License at
7010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten *
8010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten *      http://www.apache.org/licenses/LICENSE-2.0
9010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten *
10010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * Unless required by applicable law or agreed to in writing, software
11010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * distributed under the License is distributed on an "AS IS" BASIS,
12010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * See the License for the specific language governing permissions and
14010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten * limitations under the License.
15010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten */
16010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
17010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#define LOG_TAG "AudioBufferProviderSource"
18010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten//#define LOG_NDEBUG 0
19010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
20010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <cutils/compiler.h>
21010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten#include <utils/Log.h>
222dd4bdd715f586d4d30cf90cc6fc2bbfbce60fe0Glenn Kasten#include <media/nbaio/AudioBufferProviderSource.h>
23010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
24010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastennamespace android {
25010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
26010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenAudioBufferProviderSource::AudioBufferProviderSource(AudioBufferProvider *provider,
2772e54af9fcdc4754914fe2bf8de699523538b315Glenn Kasten                                                     const NBAIO_Format& format) :
28010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    NBAIO_Source(format), mProvider(provider), mConsumed(0)
29010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{
30010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    ALOG_ASSERT(provider != NULL);
316e0d67d7b496ce17c0970a4ffd3a6f808860949cGlenn Kasten    ALOG_ASSERT(Format_isValid(format));
32010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten}
33010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
34010662326b9c43c703725f933e95e0897f8a6bddGlenn KastenAudioBufferProviderSource::~AudioBufferProviderSource()
35010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{
36010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (mBuffer.raw != NULL) {
37010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mProvider->releaseBuffer(&mBuffer);
38010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
39010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten}
40010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
41010662326b9c43c703725f933e95e0897f8a6bddGlenn Kastenssize_t AudioBufferProviderSource::availableToRead()
42010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{
43010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (CC_UNLIKELY(!mNegotiated)) {
44010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        return NEGOTIATE;
45010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
46010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    return mBuffer.raw != NULL ? mBuffer.frameCount - mConsumed : 0;
47010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten}
48010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
49d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kastenssize_t AudioBufferProviderSource::read(void *buffer, size_t count)
50010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{
51010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (CC_UNLIKELY(!mNegotiated)) {
52010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        return NEGOTIATE;
53010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
54010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (CC_UNLIKELY(mBuffer.raw == NULL)) {
55010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mBuffer.frameCount = count;
56d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten        status_t status = mProvider->getNextBuffer(&mBuffer);
57010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        if (status != OK) {
58010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            return status == NOT_ENOUGH_DATA ? (ssize_t) WOULD_BLOCK : (ssize_t) status;
59010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        }
60010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        ALOG_ASSERT(mBuffer.raw != NULL);
61010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        // mConsumed is 0 either from constructor or after releaseBuffer()
62010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
63010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    size_t available = mBuffer.frameCount - mConsumed;
64010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (CC_UNLIKELY(count > available)) {
65010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        count = available;
66010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
67010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    // count could be zero, either because count was zero on entry or
68010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    // available is zero, but both are unlikely so don't check for that
694d693d6b8cc1283f92f5301daf19a07abc772a2bGlenn Kasten    memcpy(buffer, (char *) mBuffer.raw + (mConsumed * mFrameSize), count * mFrameSize);
70010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (CC_UNLIKELY((mConsumed += count) >= mBuffer.frameCount)) {
71010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mProvider->releaseBuffer(&mBuffer);
72010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mBuffer.raw = NULL;
73010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mConsumed = 0;
74010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
75010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    mFramesRead += count;
76010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    // For better responsiveness with large values of count,
77010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    // return a short count rather than continuing with next buffer.
78010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    // This gives the caller a chance to interpolate other actions.
79010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    return count;
80010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten}
81010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
82d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kastenssize_t AudioBufferProviderSource::readVia(readVia_t via, size_t total, void *user, size_t block)
83010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten{
84010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (CC_UNLIKELY(!mNegotiated)) {
85010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        return NEGOTIATE;
86010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
87010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    if (CC_UNLIKELY(block == 0)) {
88010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        block = ~0;
89010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
90010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    for (size_t accumulator = 0; ; ) {
91010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        ALOG_ASSERT(accumulator <= total);
92010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        size_t count = total - accumulator;
93010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        if (CC_UNLIKELY(count == 0)) {
94010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            return accumulator;
95010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        }
96010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        if (CC_LIKELY(count > block)) {
97010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            count = block;
98010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        }
99010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        // 1 <= count <= block
100010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        if (CC_UNLIKELY(mBuffer.raw == NULL)) {
101010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            mBuffer.frameCount = count;
102d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten            status_t status = mProvider->getNextBuffer(&mBuffer);
103010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            if (CC_LIKELY(status == OK)) {
104010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                ALOG_ASSERT(mBuffer.raw != NULL && mBuffer.frameCount <= count);
105010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                // mConsumed is 0 either from constructor or after releaseBuffer()
106010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                continue;
107010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            }
108010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            // FIXME simplify logic - does the initial count and block checks again for no reason;
109010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            //       don't you just want to fall through to the size_t available line?
110010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            if (CC_LIKELY(status == NOT_ENOUGH_DATA)) {
111010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                status = WOULD_BLOCK;
112010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            }
113010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            return accumulator > 0 ? accumulator : (ssize_t) status;
114010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        }
115010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        size_t available = mBuffer.frameCount - mConsumed;
116010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        if (CC_UNLIKELY(count > available)) {
117010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            count = available;
118010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        }
119010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        if (CC_LIKELY(count > 0)) {
120d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten            ssize_t ret = via(user, (char *) mBuffer.raw + (mConsumed * mFrameSize), count);
121d79072e9dff59f767cce2cda1caab80ce5a0815bGlenn Kasten
122010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            if (CC_UNLIKELY(ret <= 0)) {
123010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                if (CC_LIKELY(accumulator > 0)) {
124010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                    return accumulator;
125010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                }
126010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                return ret;
127010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            }
128010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            ALOG_ASSERT((size_t) ret <= count);
129010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            mFramesRead += ret;
130010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            accumulator += ret;
131010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            if (CC_LIKELY((mConsumed += ret) < mBuffer.frameCount)) {
132010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten                continue;
133010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten            }
134010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        }
135010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mProvider->releaseBuffer(&mBuffer);
136010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mBuffer.raw = NULL;
137010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        mConsumed = 0;
138010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten        // don't get next buffer until we really need it
139010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten    }
140010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten}
141010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten
142010662326b9c43c703725f933e95e0897f8a6bddGlenn Kasten}   // namespace android
143