SourceAudioBufferProvider.cpp revision 4d693d6b8cc1283f92f5301daf19a07abc772a2b
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
23namespace android {
24
25SourceAudioBufferProvider::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    mFrameBitShift = Format_frameBitShift(source->format());
41    mFrameSize = Format_frameSize(source->format());
42}
43
44SourceAudioBufferProvider::~SourceAudioBufferProvider()
45{
46    free(mAllocated);
47}
48
49status_t SourceAudioBufferProvider::getNextBuffer(Buffer *buffer, int64_t pts)
50{
51    ALOG_ASSERT(buffer != NULL && buffer->frameCount > 0 && mGetCount == 0);
52    // any leftover data available?
53    if (mRemaining > 0) {
54        ALOG_ASSERT(mOffset + mRemaining <= mSize);
55        if (mRemaining < buffer->frameCount) {
56            buffer->frameCount = mRemaining;
57        }
58        buffer->raw = (char *) mAllocated + (mOffset * mFrameSize);
59        mGetCount = buffer->frameCount;
60        return OK;
61    }
62    // do we need to reallocate?
63    if (buffer->frameCount > mSize) {
64        free(mAllocated);
65        mAllocated = malloc(buffer->frameCount * mFrameSize);
66        mSize = buffer->frameCount;
67    }
68    // read from source
69    ssize_t actual = mSource->read(mAllocated, buffer->frameCount, pts);
70    if (actual > 0) {
71        ALOG_ASSERT((size_t) actual <= buffer->frameCount);
72        mOffset = 0;
73        mRemaining = actual;
74        buffer->raw = mAllocated;
75        buffer->frameCount = actual;
76        mGetCount = actual;
77        return OK;
78    }
79    buffer->raw = NULL;
80    buffer->frameCount = 0;
81    mGetCount = 0;
82    return NOT_ENOUGH_DATA;
83}
84
85void SourceAudioBufferProvider::releaseBuffer(Buffer *buffer)
86{
87    ALOG_ASSERT((buffer != NULL) &&
88            (buffer->raw == (char *) mAllocated + (mOffset * mFrameSize)) &&
89            (buffer->frameCount <= mGetCount) &&
90            (mGetCount <= mRemaining) &&
91            (mOffset + mRemaining <= mSize));
92    mOffset += buffer->frameCount;
93    mRemaining -= buffer->frameCount;
94    mFramesReleased += buffer->frameCount;
95    buffer->raw = NULL;
96    buffer->frameCount = 0;
97    mGetCount = 0;
98}
99
100size_t SourceAudioBufferProvider::framesReady() const
101{
102    ssize_t avail = mSource->availableToRead();
103    return avail < 0 ? 0 : (size_t) avail;
104}
105
106size_t SourceAudioBufferProvider::framesReleased() const
107{
108    return mFramesReleased;
109}
110
111void SourceAudioBufferProvider::onTimestamp(const AudioTimestamp& timestamp)
112{
113    mSource->onTimestamp(timestamp);
114}
115
116}   // namespace android
117