xref: /aosp_15_r20/frameworks/av/media/libnbaio/SourceAudioBufferProvider.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
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 &timestamp)
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