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,int64_t pts)48 status_t SourceAudioBufferProvider::getNextBuffer(Buffer *buffer, int64_t pts)
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         mAllocated = malloc(buffer->frameCount * mFrameSize);
65         mSize = buffer->frameCount;
66     }
67     // read from source
68     ssize_t actual = mSource->read(mAllocated, buffer->frameCount, pts);
69     if (actual > 0) {
70         ALOG_ASSERT((size_t) actual <= buffer->frameCount);
71         mOffset = 0;
72         mRemaining = actual;
73         buffer->raw = mAllocated;
74         buffer->frameCount = actual;
75         mGetCount = actual;
76         return OK;
77     }
78     buffer->raw = NULL;
79     buffer->frameCount = 0;
80     mGetCount = 0;
81     return NOT_ENOUGH_DATA;
82 }
83 
releaseBuffer(Buffer * buffer)84 void SourceAudioBufferProvider::releaseBuffer(Buffer *buffer)
85 {
86     ALOG_ASSERT((buffer != NULL) &&
87             (buffer->raw == (char *) mAllocated + (mOffset * mFrameSize)) &&
88             (buffer->frameCount <= mGetCount) &&
89             (mGetCount <= mRemaining) &&
90             (mOffset + mRemaining <= mSize));
91     mOffset += buffer->frameCount;
92     mRemaining -= buffer->frameCount;
93     mFramesReleased += buffer->frameCount;
94     buffer->raw = NULL;
95     buffer->frameCount = 0;
96     mGetCount = 0;
97 }
98 
framesReady() const99 size_t SourceAudioBufferProvider::framesReady() const
100 {
101     ssize_t avail = mSource->availableToRead();
102     return avail < 0 ? 0 : (size_t) avail;
103 }
104 
framesReleased() const105 size_t SourceAudioBufferProvider::framesReleased() const
106 {
107     return mFramesReleased;
108 }
109 
onTimestamp(const AudioTimestamp & timestamp)110 void SourceAudioBufferProvider::onTimestamp(const AudioTimestamp& timestamp)
111 {
112     mSource->onTimestamp(timestamp);
113 }
114 
115 }   // namespace android
116