xref: /aosp_15_r20/frameworks/wilhelm/src/android/BufferQueueSource.cpp (revision bebae9c0e76121f8312ccb50385c080b3a0b023c)
1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*bebae9c0SAndroid Build Coastguard Worker  *
4*bebae9c0SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*bebae9c0SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*bebae9c0SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*bebae9c0SAndroid Build Coastguard Worker  *
8*bebae9c0SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*bebae9c0SAndroid Build Coastguard Worker  *
10*bebae9c0SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*bebae9c0SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*bebae9c0SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*bebae9c0SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*bebae9c0SAndroid Build Coastguard Worker  * limitations under the License.
15*bebae9c0SAndroid Build Coastguard Worker  */
16*bebae9c0SAndroid Build Coastguard Worker 
17*bebae9c0SAndroid Build Coastguard Worker //#define USE_LOG SLAndroidLogLevel_Verbose
18*bebae9c0SAndroid Build Coastguard Worker 
19*bebae9c0SAndroid Build Coastguard Worker #include "sles_allinclusive.h"
20*bebae9c0SAndroid Build Coastguard Worker #include "android/BufferQueueSource.h"
21*bebae9c0SAndroid Build Coastguard Worker 
22*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
23*bebae9c0SAndroid Build Coastguard Worker #include <sys/types.h>
24*bebae9c0SAndroid Build Coastguard Worker #include <unistd.h>
25*bebae9c0SAndroid Build Coastguard Worker #include <sys/types.h>
26*bebae9c0SAndroid Build Coastguard Worker #include <sys/stat.h>
27*bebae9c0SAndroid Build Coastguard Worker #include <fcntl.h>
28*bebae9c0SAndroid Build Coastguard Worker 
29*bebae9c0SAndroid Build Coastguard Worker namespace android {
30*bebae9c0SAndroid Build Coastguard Worker 
31*bebae9c0SAndroid Build Coastguard Worker 
32*bebae9c0SAndroid Build Coastguard Worker const SLuint32 BufferQueueSource::kItemProcessed[NB_BUFFEREVENT_ITEM_FIELDS] = {
33*bebae9c0SAndroid Build Coastguard Worker         SL_ANDROID_ITEMKEY_BUFFERQUEUEEVENT, // item key
34*bebae9c0SAndroid Build Coastguard Worker         sizeof(SLuint32),                    // item size
35*bebae9c0SAndroid Build Coastguard Worker         SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED // item data
36*bebae9c0SAndroid Build Coastguard Worker };
37*bebae9c0SAndroid Build Coastguard Worker 
38*bebae9c0SAndroid Build Coastguard Worker 
BufferQueueSource(IAndroidBufferQueue * androidBufferQueue)39*bebae9c0SAndroid Build Coastguard Worker BufferQueueSource::BufferQueueSource(IAndroidBufferQueue *androidBufferQueue) :
40*bebae9c0SAndroid Build Coastguard Worker           mAndroidBufferQueueSource(androidBufferQueue),
41*bebae9c0SAndroid Build Coastguard Worker           mStreamToBqOffset(0),
42*bebae9c0SAndroid Build Coastguard Worker           mEosReached(false)
43*bebae9c0SAndroid Build Coastguard Worker {
44*bebae9c0SAndroid Build Coastguard Worker }
45*bebae9c0SAndroid Build Coastguard Worker 
46*bebae9c0SAndroid Build Coastguard Worker 
~BufferQueueSource()47*bebae9c0SAndroid Build Coastguard Worker BufferQueueSource::~BufferQueueSource() {
48*bebae9c0SAndroid Build Coastguard Worker     SL_LOGD("BufferQueueSource::~BufferQueueSource");
49*bebae9c0SAndroid Build Coastguard Worker }
50*bebae9c0SAndroid Build Coastguard Worker 
51*bebae9c0SAndroid Build Coastguard Worker 
52*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------------------------------
initCheck() const53*bebae9c0SAndroid Build Coastguard Worker status_t BufferQueueSource::initCheck() const {
54*bebae9c0SAndroid Build Coastguard Worker     return mAndroidBufferQueueSource != NULL ? OK : NO_INIT;
55*bebae9c0SAndroid Build Coastguard Worker }
56*bebae9c0SAndroid Build Coastguard Worker 
readAt(off64_t offset,void * data,size_t size)57*bebae9c0SAndroid Build Coastguard Worker ssize_t BufferQueueSource::readAt(off64_t offset, void *data, size_t size) {
58*bebae9c0SAndroid Build Coastguard Worker     SL_LOGD("BufferQueueSource::readAt(offset=%lld, data=%p, size=%d)", offset, data, size);
59*bebae9c0SAndroid Build Coastguard Worker 
60*bebae9c0SAndroid Build Coastguard Worker     if (mEosReached) {
61*bebae9c0SAndroid Build Coastguard Worker         // once EOS has been received from the buffer queue, you can't read anymore
62*bebae9c0SAndroid Build Coastguard Worker         return 0;
63*bebae9c0SAndroid Build Coastguard Worker     }
64*bebae9c0SAndroid Build Coastguard Worker 
65*bebae9c0SAndroid Build Coastguard Worker     ssize_t readSize;
66*bebae9c0SAndroid Build Coastguard Worker     slAndroidBufferQueueCallback callback = NULL;
67*bebae9c0SAndroid Build Coastguard Worker     void* pBufferContext, *pBufferData, *callbackPContext;
68*bebae9c0SAndroid Build Coastguard Worker     uint32_t dataSize, dataUsed;
69*bebae9c0SAndroid Build Coastguard Worker 
70*bebae9c0SAndroid Build Coastguard Worker     interface_lock_exclusive(mAndroidBufferQueueSource);
71*bebae9c0SAndroid Build Coastguard Worker 
72*bebae9c0SAndroid Build Coastguard Worker     if (mAndroidBufferQueueSource->mState.count == 0) {
73*bebae9c0SAndroid Build Coastguard Worker         readSize = 0;
74*bebae9c0SAndroid Build Coastguard Worker     } else {
75*bebae9c0SAndroid Build Coastguard Worker         assert(mAndroidBufferQueueSource->mFront != mAndroidBufferQueueSource->mRear);
76*bebae9c0SAndroid Build Coastguard Worker 
77*bebae9c0SAndroid Build Coastguard Worker         AdvancedBufferHeader *oldFront = mAndroidBufferQueueSource->mFront;
78*bebae9c0SAndroid Build Coastguard Worker         AdvancedBufferHeader *newFront = &oldFront[1];
79*bebae9c0SAndroid Build Coastguard Worker 
80*bebae9c0SAndroid Build Coastguard Worker         // where to read from
81*bebae9c0SAndroid Build Coastguard Worker         char *pSrc = NULL;
82*bebae9c0SAndroid Build Coastguard Worker         // can this read operation cause us to call the buffer queue callback
83*bebae9c0SAndroid Build Coastguard Worker         // (either because there was a command with no data, or all the data has been consumed)
84*bebae9c0SAndroid Build Coastguard Worker         bool queueCallbackCandidate = false;
85*bebae9c0SAndroid Build Coastguard Worker 
86*bebae9c0SAndroid Build Coastguard Worker         // consume events when starting to read data from a buffer for the first time
87*bebae9c0SAndroid Build Coastguard Worker         if (oldFront->mDataSizeConsumed == 0) {
88*bebae9c0SAndroid Build Coastguard Worker             if (oldFront->mItems.mAdtsCmdData.mAdtsCmdCode & ANDROID_ADTSEVENT_EOS) {
89*bebae9c0SAndroid Build Coastguard Worker                 mEosReached = true;
90*bebae9c0SAndroid Build Coastguard Worker                 // EOS has no associated data
91*bebae9c0SAndroid Build Coastguard Worker                 queueCallbackCandidate = true;
92*bebae9c0SAndroid Build Coastguard Worker             }
93*bebae9c0SAndroid Build Coastguard Worker             oldFront->mItems.mAdtsCmdData.mAdtsCmdCode = ANDROID_ADTSEVENT_NONE;
94*bebae9c0SAndroid Build Coastguard Worker         }
95*bebae9c0SAndroid Build Coastguard Worker 
96*bebae9c0SAndroid Build Coastguard Worker         //assert(mStreamToBqOffset <= offset);
97*bebae9c0SAndroid Build Coastguard Worker         CHECK_LE(mStreamToBqOffset, offset);
98*bebae9c0SAndroid Build Coastguard Worker 
99*bebae9c0SAndroid Build Coastguard Worker         if (offset + (off64_t) size <= mStreamToBqOffset + oldFront->mDataSize) {
100*bebae9c0SAndroid Build Coastguard Worker             pSrc = ((char*)oldFront->mDataBuffer) + (offset - mStreamToBqOffset);
101*bebae9c0SAndroid Build Coastguard Worker 
102*bebae9c0SAndroid Build Coastguard Worker             if (offset - mStreamToBqOffset + size == oldFront->mDataSize) {
103*bebae9c0SAndroid Build Coastguard Worker                 // consumed buffer entirely
104*bebae9c0SAndroid Build Coastguard Worker                 oldFront->mDataSizeConsumed = oldFront->mDataSize;
105*bebae9c0SAndroid Build Coastguard Worker                 mStreamToBqOffset += oldFront->mDataSize;
106*bebae9c0SAndroid Build Coastguard Worker                 queueCallbackCandidate = true;
107*bebae9c0SAndroid Build Coastguard Worker 
108*bebae9c0SAndroid Build Coastguard Worker                 // move queue to next buffer
109*bebae9c0SAndroid Build Coastguard Worker                 if (newFront == &mAndroidBufferQueueSource->
110*bebae9c0SAndroid Build Coastguard Worker                         mBufferArray[mAndroidBufferQueueSource->mNumBuffers + 1]) {
111*bebae9c0SAndroid Build Coastguard Worker                     // reached the end, circle back
112*bebae9c0SAndroid Build Coastguard Worker                     newFront = mAndroidBufferQueueSource->mBufferArray;
113*bebae9c0SAndroid Build Coastguard Worker                 }
114*bebae9c0SAndroid Build Coastguard Worker                 mAndroidBufferQueueSource->mFront = newFront;
115*bebae9c0SAndroid Build Coastguard Worker                 // update the queue state
116*bebae9c0SAndroid Build Coastguard Worker                 mAndroidBufferQueueSource->mState.count--;
117*bebae9c0SAndroid Build Coastguard Worker                 mAndroidBufferQueueSource->mState.index++;
118*bebae9c0SAndroid Build Coastguard Worker                 SL_LOGV("BufferQueueSource moving to next buffer");
119*bebae9c0SAndroid Build Coastguard Worker             }
120*bebae9c0SAndroid Build Coastguard Worker         }
121*bebae9c0SAndroid Build Coastguard Worker 
122*bebae9c0SAndroid Build Coastguard Worker         // consume data: copy to given destination
123*bebae9c0SAndroid Build Coastguard Worker         if (NULL != pSrc) {
124*bebae9c0SAndroid Build Coastguard Worker             memcpy(data, pSrc, size);
125*bebae9c0SAndroid Build Coastguard Worker             readSize = size;
126*bebae9c0SAndroid Build Coastguard Worker         } else {
127*bebae9c0SAndroid Build Coastguard Worker             readSize = 0;
128*bebae9c0SAndroid Build Coastguard Worker         }
129*bebae9c0SAndroid Build Coastguard Worker 
130*bebae9c0SAndroid Build Coastguard Worker         if (queueCallbackCandidate) {
131*bebae9c0SAndroid Build Coastguard Worker             // data has been consumed, and the buffer queue state has been updated
132*bebae9c0SAndroid Build Coastguard Worker             // we will notify the client if applicable
133*bebae9c0SAndroid Build Coastguard Worker             if (mAndroidBufferQueueSource->mCallbackEventsMask &
134*bebae9c0SAndroid Build Coastguard Worker                     SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED) {
135*bebae9c0SAndroid Build Coastguard Worker                 callback = mAndroidBufferQueueSource->mCallback;
136*bebae9c0SAndroid Build Coastguard Worker                 // save callback data while under lock
137*bebae9c0SAndroid Build Coastguard Worker                 callbackPContext = mAndroidBufferQueueSource->mContext;
138*bebae9c0SAndroid Build Coastguard Worker                 pBufferContext = (void *)oldFront->mBufferContext;
139*bebae9c0SAndroid Build Coastguard Worker                 pBufferData    = (void *)oldFront->mDataBuffer;
140*bebae9c0SAndroid Build Coastguard Worker                 dataSize       = oldFront->mDataSize;
141*bebae9c0SAndroid Build Coastguard Worker                 dataUsed       = oldFront->mDataSizeConsumed;
142*bebae9c0SAndroid Build Coastguard Worker             }
143*bebae9c0SAndroid Build Coastguard Worker         }
144*bebae9c0SAndroid Build Coastguard Worker     }
145*bebae9c0SAndroid Build Coastguard Worker 
146*bebae9c0SAndroid Build Coastguard Worker     interface_unlock_exclusive(mAndroidBufferQueueSource);
147*bebae9c0SAndroid Build Coastguard Worker 
148*bebae9c0SAndroid Build Coastguard Worker     // notify client
149*bebae9c0SAndroid Build Coastguard Worker     if (NULL != callback) {
150*bebae9c0SAndroid Build Coastguard Worker         SLresult result = (*callback)(&mAndroidBufferQueueSource->mItf, callbackPContext,
151*bebae9c0SAndroid Build Coastguard Worker                 pBufferContext, pBufferData, dataSize, dataUsed,
152*bebae9c0SAndroid Build Coastguard Worker                 // no messages during playback other than marking the buffer as processed
153*bebae9c0SAndroid Build Coastguard Worker                 (const SLAndroidBufferItem*)(&kItemProcessed) /* pItems */,
154*bebae9c0SAndroid Build Coastguard Worker                 NB_BUFFEREVENT_ITEM_FIELDS * sizeof(SLuint32) /* itemsLength */ );
155*bebae9c0SAndroid Build Coastguard Worker         if (SL_RESULT_SUCCESS != result) {
156*bebae9c0SAndroid Build Coastguard Worker             // Reserved for future use
157*bebae9c0SAndroid Build Coastguard Worker             SL_LOGW("Unsuccessful result %d returned from AndroidBufferQueueCallback", result);
158*bebae9c0SAndroid Build Coastguard Worker         }
159*bebae9c0SAndroid Build Coastguard Worker     }
160*bebae9c0SAndroid Build Coastguard Worker 
161*bebae9c0SAndroid Build Coastguard Worker     return readSize;
162*bebae9c0SAndroid Build Coastguard Worker }
163*bebae9c0SAndroid Build Coastguard Worker 
164*bebae9c0SAndroid Build Coastguard Worker 
getSize(off64_t * size)165*bebae9c0SAndroid Build Coastguard Worker status_t BufferQueueSource::getSize(off64_t *size) {
166*bebae9c0SAndroid Build Coastguard Worker     SL_LOGD("BufferQueueSource::getSize()");
167*bebae9c0SAndroid Build Coastguard Worker     // we're streaming, we don't know how much there is
168*bebae9c0SAndroid Build Coastguard Worker     *size = 0;
169*bebae9c0SAndroid Build Coastguard Worker     return ERROR_UNSUPPORTED;
170*bebae9c0SAndroid Build Coastguard Worker }
171*bebae9c0SAndroid Build Coastguard Worker 
172*bebae9c0SAndroid Build Coastguard Worker }  // namespace android
173