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