1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2012 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "SourceAudioBufferProvider"
18*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
19*ec779b8eSAndroid Build Coastguard Worker
20*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
21*ec779b8eSAndroid Build Coastguard Worker #include <media/nbaio/SourceAudioBufferProvider.h>
22*ec779b8eSAndroid Build Coastguard Worker
23*ec779b8eSAndroid Build Coastguard Worker namespace android {
24*ec779b8eSAndroid Build Coastguard Worker
SourceAudioBufferProvider(const sp<NBAIO_Source> & source)25*ec779b8eSAndroid Build Coastguard Worker SourceAudioBufferProvider::SourceAudioBufferProvider(const sp<NBAIO_Source>& source) :
26*ec779b8eSAndroid Build Coastguard Worker mSource(source),
27*ec779b8eSAndroid Build Coastguard Worker // mFrameSize below
28*ec779b8eSAndroid Build Coastguard Worker mAllocated(NULL), mSize(0), mOffset(0), mRemaining(0), mGetCount(0), mFramesReleased(0)
29*ec779b8eSAndroid Build Coastguard Worker {
30*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT(source != 0);
31*ec779b8eSAndroid Build Coastguard Worker
32*ec779b8eSAndroid Build Coastguard Worker // negotiate with source
33*ec779b8eSAndroid Build Coastguard Worker NBAIO_Format counterOffers[1];
34*ec779b8eSAndroid Build Coastguard Worker size_t numCounterOffers = 1;
35*ec779b8eSAndroid Build Coastguard Worker [[maybe_unused]] ssize_t index = source->negotiate(NULL, 0, counterOffers, numCounterOffers);
36*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT(index == (ssize_t) NEGOTIATE && numCounterOffers > 0);
37*ec779b8eSAndroid Build Coastguard Worker numCounterOffers = 0;
38*ec779b8eSAndroid Build Coastguard Worker index = source->negotiate(counterOffers, 1, NULL, numCounterOffers);
39*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT(index == 0);
40*ec779b8eSAndroid Build Coastguard Worker mFrameSize = Format_frameSize(source->format());
41*ec779b8eSAndroid Build Coastguard Worker }
42*ec779b8eSAndroid Build Coastguard Worker
~SourceAudioBufferProvider()43*ec779b8eSAndroid Build Coastguard Worker SourceAudioBufferProvider::~SourceAudioBufferProvider()
44*ec779b8eSAndroid Build Coastguard Worker {
45*ec779b8eSAndroid Build Coastguard Worker free(mAllocated);
46*ec779b8eSAndroid Build Coastguard Worker }
47*ec779b8eSAndroid Build Coastguard Worker
getNextBuffer(Buffer * buffer)48*ec779b8eSAndroid Build Coastguard Worker status_t SourceAudioBufferProvider::getNextBuffer(Buffer *buffer)
49*ec779b8eSAndroid Build Coastguard Worker {
50*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT(buffer != NULL && buffer->frameCount > 0 && mGetCount == 0);
51*ec779b8eSAndroid Build Coastguard Worker // any leftover data available?
52*ec779b8eSAndroid Build Coastguard Worker if (mRemaining > 0) {
53*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT(mOffset + mRemaining <= mSize);
54*ec779b8eSAndroid Build Coastguard Worker if (mRemaining < buffer->frameCount) {
55*ec779b8eSAndroid Build Coastguard Worker buffer->frameCount = mRemaining;
56*ec779b8eSAndroid Build Coastguard Worker }
57*ec779b8eSAndroid Build Coastguard Worker buffer->raw = (char *) mAllocated + (mOffset * mFrameSize);
58*ec779b8eSAndroid Build Coastguard Worker mGetCount = buffer->frameCount;
59*ec779b8eSAndroid Build Coastguard Worker return OK;
60*ec779b8eSAndroid Build Coastguard Worker }
61*ec779b8eSAndroid Build Coastguard Worker // do we need to reallocate?
62*ec779b8eSAndroid Build Coastguard Worker if (buffer->frameCount > mSize) {
63*ec779b8eSAndroid Build Coastguard Worker free(mAllocated);
64*ec779b8eSAndroid Build Coastguard Worker // Android convention is to _not_ check the return value of malloc and friends.
65*ec779b8eSAndroid Build Coastguard Worker // But in this case the calloc() can also fail due to integer overflow,
66*ec779b8eSAndroid Build Coastguard Worker // so we check and recover.
67*ec779b8eSAndroid Build Coastguard Worker mAllocated = calloc(buffer->frameCount, mFrameSize);
68*ec779b8eSAndroid Build Coastguard Worker if (mAllocated == NULL) {
69*ec779b8eSAndroid Build Coastguard Worker mSize = 0;
70*ec779b8eSAndroid Build Coastguard Worker goto fail;
71*ec779b8eSAndroid Build Coastguard Worker }
72*ec779b8eSAndroid Build Coastguard Worker mSize = buffer->frameCount;
73*ec779b8eSAndroid Build Coastguard Worker }
74*ec779b8eSAndroid Build Coastguard Worker {
75*ec779b8eSAndroid Build Coastguard Worker // read from source
76*ec779b8eSAndroid Build Coastguard Worker ssize_t actual = mSource->read(mAllocated, buffer->frameCount);
77*ec779b8eSAndroid Build Coastguard Worker if (actual > 0) {
78*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT((size_t) actual <= buffer->frameCount);
79*ec779b8eSAndroid Build Coastguard Worker mOffset = 0;
80*ec779b8eSAndroid Build Coastguard Worker mRemaining = actual;
81*ec779b8eSAndroid Build Coastguard Worker buffer->raw = mAllocated;
82*ec779b8eSAndroid Build Coastguard Worker buffer->frameCount = actual;
83*ec779b8eSAndroid Build Coastguard Worker mGetCount = actual;
84*ec779b8eSAndroid Build Coastguard Worker return OK;
85*ec779b8eSAndroid Build Coastguard Worker }
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker fail:
88*ec779b8eSAndroid Build Coastguard Worker buffer->raw = NULL;
89*ec779b8eSAndroid Build Coastguard Worker buffer->frameCount = 0;
90*ec779b8eSAndroid Build Coastguard Worker mGetCount = 0;
91*ec779b8eSAndroid Build Coastguard Worker return NOT_ENOUGH_DATA;
92*ec779b8eSAndroid Build Coastguard Worker }
93*ec779b8eSAndroid Build Coastguard Worker
releaseBuffer(Buffer * buffer)94*ec779b8eSAndroid Build Coastguard Worker void SourceAudioBufferProvider::releaseBuffer(Buffer *buffer)
95*ec779b8eSAndroid Build Coastguard Worker {
96*ec779b8eSAndroid Build Coastguard Worker ALOG_ASSERT((buffer != NULL) &&
97*ec779b8eSAndroid Build Coastguard Worker (buffer->raw == (char *) mAllocated + (mOffset * mFrameSize)) &&
98*ec779b8eSAndroid Build Coastguard Worker (buffer->frameCount <= mGetCount) &&
99*ec779b8eSAndroid Build Coastguard Worker (mGetCount <= mRemaining) &&
100*ec779b8eSAndroid Build Coastguard Worker (mOffset + mRemaining <= mSize));
101*ec779b8eSAndroid Build Coastguard Worker mOffset += buffer->frameCount;
102*ec779b8eSAndroid Build Coastguard Worker mRemaining -= buffer->frameCount;
103*ec779b8eSAndroid Build Coastguard Worker mFramesReleased += buffer->frameCount;
104*ec779b8eSAndroid Build Coastguard Worker buffer->raw = NULL;
105*ec779b8eSAndroid Build Coastguard Worker buffer->frameCount = 0;
106*ec779b8eSAndroid Build Coastguard Worker mGetCount = 0;
107*ec779b8eSAndroid Build Coastguard Worker }
108*ec779b8eSAndroid Build Coastguard Worker
framesReady() const109*ec779b8eSAndroid Build Coastguard Worker size_t SourceAudioBufferProvider::framesReady() const
110*ec779b8eSAndroid Build Coastguard Worker {
111*ec779b8eSAndroid Build Coastguard Worker ssize_t avail = mSource->availableToRead();
112*ec779b8eSAndroid Build Coastguard Worker return avail < 0 ? 0 : (size_t) avail;
113*ec779b8eSAndroid Build Coastguard Worker }
114*ec779b8eSAndroid Build Coastguard Worker
framesReleased() const115*ec779b8eSAndroid Build Coastguard Worker int64_t SourceAudioBufferProvider::framesReleased() const
116*ec779b8eSAndroid Build Coastguard Worker {
117*ec779b8eSAndroid Build Coastguard Worker return mFramesReleased;
118*ec779b8eSAndroid Build Coastguard Worker }
119*ec779b8eSAndroid Build Coastguard Worker
onTimestamp(const ExtendedTimestamp & timestamp)120*ec779b8eSAndroid Build Coastguard Worker void SourceAudioBufferProvider::onTimestamp(const ExtendedTimestamp ×tamp)
121*ec779b8eSAndroid Build Coastguard Worker {
122*ec779b8eSAndroid Build Coastguard Worker mSource->onTimestamp(timestamp);
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker
125*ec779b8eSAndroid Build Coastguard Worker } // namespace android
126