1*bebae9c0SAndroid Build Coastguard Worker /*
2*bebae9c0SAndroid Build Coastguard Worker * Copyright (C) 2010 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_StreamPlayer.h"
21*bebae9c0SAndroid Build Coastguard Worker
22*bebae9c0SAndroid Build Coastguard Worker #include <media/IStreamSource.h>
23*bebae9c0SAndroid Build Coastguard Worker #include <media/IMediaPlayerService.h>
24*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/foundation/ADebug.h>
25*bebae9c0SAndroid Build Coastguard Worker #include <media/stagefright/foundation/MediaKeys.h>
26*bebae9c0SAndroid Build Coastguard Worker #include <mpeg2ts/ATSParser.h>
27*bebae9c0SAndroid Build Coastguard Worker #include <binder/IPCThreadState.h>
28*bebae9c0SAndroid Build Coastguard Worker
29*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
30*bebae9c0SAndroid Build Coastguard Worker namespace android {
31*bebae9c0SAndroid Build Coastguard Worker
StreamSourceAppProxy(IAndroidBufferQueue * androidBufferQueue,const sp<CallbackProtector> & callbackProtector,StreamPlayer * player)32*bebae9c0SAndroid Build Coastguard Worker StreamSourceAppProxy::StreamSourceAppProxy(
33*bebae9c0SAndroid Build Coastguard Worker IAndroidBufferQueue *androidBufferQueue,
34*bebae9c0SAndroid Build Coastguard Worker const sp<CallbackProtector> &callbackProtector,
35*bebae9c0SAndroid Build Coastguard Worker // sp<StreamPlayer> would cause StreamPlayer's destructor to run during it's own
36*bebae9c0SAndroid Build Coastguard Worker // construction. If you pass in a sp<> to 'this' inside a constructor, then first the
37*bebae9c0SAndroid Build Coastguard Worker // refcount is increased from 0 to 1, then decreased from 1 to 0, which causes the object's
38*bebae9c0SAndroid Build Coastguard Worker // destructor to run from inside it's own constructor.
39*bebae9c0SAndroid Build Coastguard Worker StreamPlayer * /* const sp<StreamPlayer> & */ player) :
40*bebae9c0SAndroid Build Coastguard Worker mBuffersHasBeenSet(false),
41*bebae9c0SAndroid Build Coastguard Worker mAndroidBufferQueue(androidBufferQueue),
42*bebae9c0SAndroid Build Coastguard Worker mCallbackProtector(callbackProtector),
43*bebae9c0SAndroid Build Coastguard Worker mPlayer(player)
44*bebae9c0SAndroid Build Coastguard Worker {
45*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("StreamSourceAppProxy::StreamSourceAppProxy()");
46*bebae9c0SAndroid Build Coastguard Worker }
47*bebae9c0SAndroid Build Coastguard Worker
~StreamSourceAppProxy()48*bebae9c0SAndroid Build Coastguard Worker StreamSourceAppProxy::~StreamSourceAppProxy() {
49*bebae9c0SAndroid Build Coastguard Worker SL_LOGV("StreamSourceAppProxy::~StreamSourceAppProxy()");
50*bebae9c0SAndroid Build Coastguard Worker disconnect();
51*bebae9c0SAndroid Build Coastguard Worker }
52*bebae9c0SAndroid Build Coastguard Worker
53*bebae9c0SAndroid Build Coastguard Worker const SLuint32 StreamSourceAppProxy::kItemProcessed[NB_BUFFEREVENT_ITEM_FIELDS] = {
54*bebae9c0SAndroid Build Coastguard Worker SL_ANDROID_ITEMKEY_BUFFERQUEUEEVENT, // item key
55*bebae9c0SAndroid Build Coastguard Worker sizeof(SLuint32), // item size
56*bebae9c0SAndroid Build Coastguard Worker SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED // item data
57*bebae9c0SAndroid Build Coastguard Worker };
58*bebae9c0SAndroid Build Coastguard Worker
59*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
60*bebae9c0SAndroid Build Coastguard Worker // IStreamSource implementation
setListener(const sp<IStreamListener> & listener)61*bebae9c0SAndroid Build Coastguard Worker void StreamSourceAppProxy::setListener(const sp<IStreamListener> &listener) {
62*bebae9c0SAndroid Build Coastguard Worker assert(listener != NULL);
63*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
64*bebae9c0SAndroid Build Coastguard Worker assert(mListener == NULL);
65*bebae9c0SAndroid Build Coastguard Worker mListener = listener;
66*bebae9c0SAndroid Build Coastguard Worker }
67*bebae9c0SAndroid Build Coastguard Worker
setBuffers(const Vector<sp<IMemory>> & buffers)68*bebae9c0SAndroid Build Coastguard Worker void StreamSourceAppProxy::setBuffers(const Vector<sp<IMemory> > &buffers) {
69*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
70*bebae9c0SAndroid Build Coastguard Worker assert(!mBuffersHasBeenSet);
71*bebae9c0SAndroid Build Coastguard Worker mBuffers = buffers;
72*bebae9c0SAndroid Build Coastguard Worker mBuffersHasBeenSet = true;
73*bebae9c0SAndroid Build Coastguard Worker }
74*bebae9c0SAndroid Build Coastguard Worker
onBufferAvailable(size_t index)75*bebae9c0SAndroid Build Coastguard Worker void StreamSourceAppProxy::onBufferAvailable(size_t index) {
76*bebae9c0SAndroid Build Coastguard Worker //SL_LOGD("StreamSourceAppProxy::onBufferAvailable(%d)", index);
77*bebae9c0SAndroid Build Coastguard Worker
78*bebae9c0SAndroid Build Coastguard Worker {
79*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
80*bebae9c0SAndroid Build Coastguard Worker if (!mBuffersHasBeenSet) {
81*bebae9c0SAndroid Build Coastguard Worker // no buffers available to push data to from the buffer queue, bail
82*bebae9c0SAndroid Build Coastguard Worker return;
83*bebae9c0SAndroid Build Coastguard Worker }
84*bebae9c0SAndroid Build Coastguard Worker CHECK_LT(index, mBuffers.size());
85*bebae9c0SAndroid Build Coastguard Worker #if 0 // enable if needed for debugging
86*bebae9c0SAndroid Build Coastguard Worker sp<IMemory> mem = mBuffers.itemAt(index);
87*bebae9c0SAndroid Build Coastguard Worker SLAint64 length = (SLAint64) mem->size();
88*bebae9c0SAndroid Build Coastguard Worker #endif
89*bebae9c0SAndroid Build Coastguard Worker mAvailableBuffers.push_back(index);
90*bebae9c0SAndroid Build Coastguard Worker //SL_LOGD("onBufferAvailable() now %d buffers available in queue",
91*bebae9c0SAndroid Build Coastguard Worker // mAvailableBuffers.size());
92*bebae9c0SAndroid Build Coastguard Worker }
93*bebae9c0SAndroid Build Coastguard Worker
94*bebae9c0SAndroid Build Coastguard Worker // a new shared mem buffer is available: let's try to fill immediately
95*bebae9c0SAndroid Build Coastguard Worker pullFromBuffQueue();
96*bebae9c0SAndroid Build Coastguard Worker }
97*bebae9c0SAndroid Build Coastguard Worker
receivedCmd_l(IStreamListener::Command cmd,const sp<AMessage> & msg)98*bebae9c0SAndroid Build Coastguard Worker void StreamSourceAppProxy::receivedCmd_l(IStreamListener::Command cmd, const sp<AMessage> &msg) {
99*bebae9c0SAndroid Build Coastguard Worker if (mListener != 0) {
100*bebae9c0SAndroid Build Coastguard Worker mListener->issueCommand(cmd, false /* synchronous */, msg);
101*bebae9c0SAndroid Build Coastguard Worker }
102*bebae9c0SAndroid Build Coastguard Worker }
103*bebae9c0SAndroid Build Coastguard Worker
receivedBuffer_l(size_t buffIndex,size_t buffLength)104*bebae9c0SAndroid Build Coastguard Worker void StreamSourceAppProxy::receivedBuffer_l(size_t buffIndex, size_t buffLength) {
105*bebae9c0SAndroid Build Coastguard Worker if (mListener != 0) {
106*bebae9c0SAndroid Build Coastguard Worker mListener->queueBuffer(buffIndex, buffLength);
107*bebae9c0SAndroid Build Coastguard Worker }
108*bebae9c0SAndroid Build Coastguard Worker }
109*bebae9c0SAndroid Build Coastguard Worker
disconnect()110*bebae9c0SAndroid Build Coastguard Worker void StreamSourceAppProxy::disconnect() {
111*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
112*bebae9c0SAndroid Build Coastguard Worker mListener.clear();
113*bebae9c0SAndroid Build Coastguard Worker // Force binder to push the decremented reference count for sp<IStreamListener>.
114*bebae9c0SAndroid Build Coastguard Worker // mediaserver and client both have sp<> to the other. When you decrement an sp<>
115*bebae9c0SAndroid Build Coastguard Worker // reference count, binder doesn't push that to the other process immediately.
116*bebae9c0SAndroid Build Coastguard Worker IPCThreadState::self()->flushCommands();
117*bebae9c0SAndroid Build Coastguard Worker mBuffers.clear();
118*bebae9c0SAndroid Build Coastguard Worker mBuffersHasBeenSet = false;
119*bebae9c0SAndroid Build Coastguard Worker mAvailableBuffers.clear();
120*bebae9c0SAndroid Build Coastguard Worker }
121*bebae9c0SAndroid Build Coastguard Worker
122*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
123*bebae9c0SAndroid Build Coastguard Worker // consumption from ABQ: pull from the ABQ, and push to shared memory (media server)
pullFromBuffQueue()124*bebae9c0SAndroid Build Coastguard Worker void StreamSourceAppProxy::pullFromBuffQueue() {
125*bebae9c0SAndroid Build Coastguard Worker
126*bebae9c0SAndroid Build Coastguard Worker if (android::CallbackProtector::enterCbIfOk(mCallbackProtector)) {
127*bebae9c0SAndroid Build Coastguard Worker
128*bebae9c0SAndroid Build Coastguard Worker size_t bufferId;
129*bebae9c0SAndroid Build Coastguard Worker void* bufferLoc;
130*bebae9c0SAndroid Build Coastguard Worker size_t buffSize;
131*bebae9c0SAndroid Build Coastguard Worker
132*bebae9c0SAndroid Build Coastguard Worker slAndroidBufferQueueCallback callback = NULL;
133*bebae9c0SAndroid Build Coastguard Worker void* pBufferContext, *pBufferData, *callbackPContext = NULL;
134*bebae9c0SAndroid Build Coastguard Worker AdvancedBufferHeader *oldFront = NULL;
135*bebae9c0SAndroid Build Coastguard Worker uint32_t dataSize /* , dataUsed */;
136*bebae9c0SAndroid Build Coastguard Worker
137*bebae9c0SAndroid Build Coastguard Worker // retrieve data from the buffer queue
138*bebae9c0SAndroid Build Coastguard Worker interface_lock_exclusive(mAndroidBufferQueue);
139*bebae9c0SAndroid Build Coastguard Worker
140*bebae9c0SAndroid Build Coastguard Worker // can this read operation cause us to call the buffer queue callback
141*bebae9c0SAndroid Build Coastguard Worker // (either because there was a command with no data, or all the data has been consumed)
142*bebae9c0SAndroid Build Coastguard Worker bool queueCallbackCandidate = false;
143*bebae9c0SAndroid Build Coastguard Worker
144*bebae9c0SAndroid Build Coastguard Worker if (mAndroidBufferQueue->mState.count != 0) {
145*bebae9c0SAndroid Build Coastguard Worker // SL_LOGD("nbBuffers in ABQ = %u, buffSize=%u",abq->mState.count, buffSize);
146*bebae9c0SAndroid Build Coastguard Worker assert(mAndroidBufferQueue->mFront != mAndroidBufferQueue->mRear);
147*bebae9c0SAndroid Build Coastguard Worker
148*bebae9c0SAndroid Build Coastguard Worker oldFront = mAndroidBufferQueue->mFront;
149*bebae9c0SAndroid Build Coastguard Worker AdvancedBufferHeader *newFront = &oldFront[1];
150*bebae9c0SAndroid Build Coastguard Worker
151*bebae9c0SAndroid Build Coastguard Worker // consume events when starting to read data from a buffer for the first time
152*bebae9c0SAndroid Build Coastguard Worker if (oldFront->mDataSizeConsumed == 0) {
153*bebae9c0SAndroid Build Coastguard Worker // note this code assumes at most one event per buffer; see IAndroidBufferQueue_Enqueue
154*bebae9c0SAndroid Build Coastguard Worker if (oldFront->mItems.mTsCmdData.mTsCmdCode & ANDROID_MP2TSEVENT_EOS) {
155*bebae9c0SAndroid Build Coastguard Worker receivedCmd_l(IStreamListener::EOS);
156*bebae9c0SAndroid Build Coastguard Worker // EOS has no associated data
157*bebae9c0SAndroid Build Coastguard Worker queueCallbackCandidate = true;
158*bebae9c0SAndroid Build Coastguard Worker } else if (oldFront->mItems.mTsCmdData.mTsCmdCode & ANDROID_MP2TSEVENT_DISCONTINUITY) {
159*bebae9c0SAndroid Build Coastguard Worker receivedCmd_l(IStreamListener::DISCONTINUITY);
160*bebae9c0SAndroid Build Coastguard Worker } else if (oldFront->mItems.mTsCmdData.mTsCmdCode & ANDROID_MP2TSEVENT_DISCON_NEWPTS) {
161*bebae9c0SAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage();
162*bebae9c0SAndroid Build Coastguard Worker msg->setInt64(kATSParserKeyResumeAtPTS,
163*bebae9c0SAndroid Build Coastguard Worker (int64_t)oldFront->mItems.mTsCmdData.mPts);
164*bebae9c0SAndroid Build Coastguard Worker receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
165*bebae9c0SAndroid Build Coastguard Worker } else if (oldFront->mItems.mTsCmdData.mTsCmdCode
166*bebae9c0SAndroid Build Coastguard Worker & ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL) {
167*bebae9c0SAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage();
168*bebae9c0SAndroid Build Coastguard Worker msg->setInt32(
169*bebae9c0SAndroid Build Coastguard Worker kIStreamListenerKeyDiscontinuityMask,
170*bebae9c0SAndroid Build Coastguard Worker ATSParser::DISCONTINUITY_FORMATCHANGE);
171*bebae9c0SAndroid Build Coastguard Worker receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
172*bebae9c0SAndroid Build Coastguard Worker } else if (oldFront->mItems.mTsCmdData.mTsCmdCode
173*bebae9c0SAndroid Build Coastguard Worker & ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO) {
174*bebae9c0SAndroid Build Coastguard Worker sp<AMessage> msg = new AMessage();
175*bebae9c0SAndroid Build Coastguard Worker msg->setInt32(
176*bebae9c0SAndroid Build Coastguard Worker kIStreamListenerKeyDiscontinuityMask,
177*bebae9c0SAndroid Build Coastguard Worker ATSParser::DISCONTINUITY_VIDEO_FORMAT);
178*bebae9c0SAndroid Build Coastguard Worker receivedCmd_l(IStreamListener::DISCONTINUITY, msg /*msg*/);
179*bebae9c0SAndroid Build Coastguard Worker }
180*bebae9c0SAndroid Build Coastguard Worker // note that here we are intentionally only supporting
181*bebae9c0SAndroid Build Coastguard Worker // ANDROID_MP2TSEVENT_FORMAT_CHANGE_VIDEO, see IAndroidBufferQueue.c
182*bebae9c0SAndroid Build Coastguard Worker
183*bebae9c0SAndroid Build Coastguard Worker // some commands may introduce a time discontinuity, reevaluate position if needed
184*bebae9c0SAndroid Build Coastguard Worker if (oldFront->mItems.mTsCmdData.mTsCmdCode & (ANDROID_MP2TSEVENT_DISCONTINUITY |
185*bebae9c0SAndroid Build Coastguard Worker ANDROID_MP2TSEVENT_DISCON_NEWPTS | ANDROID_MP2TSEVENT_FORMAT_CHANGE_FULL)) {
186*bebae9c0SAndroid Build Coastguard Worker const sp<StreamPlayer> player(mPlayer.promote());
187*bebae9c0SAndroid Build Coastguard Worker if (player != NULL) {
188*bebae9c0SAndroid Build Coastguard Worker // FIXME see note at onSeek
189*bebae9c0SAndroid Build Coastguard Worker player->seek(ANDROID_UNKNOWN_TIME);
190*bebae9c0SAndroid Build Coastguard Worker }
191*bebae9c0SAndroid Build Coastguard Worker }
192*bebae9c0SAndroid Build Coastguard Worker oldFront->mItems.mTsCmdData.mTsCmdCode = ANDROID_MP2TSEVENT_NONE;
193*bebae9c0SAndroid Build Coastguard Worker }
194*bebae9c0SAndroid Build Coastguard Worker
195*bebae9c0SAndroid Build Coastguard Worker {
196*bebae9c0SAndroid Build Coastguard Worker // we're going to change the shared mem buffer queue, so lock it
197*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mLock);
198*bebae9c0SAndroid Build Coastguard Worker if (!mAvailableBuffers.empty()) {
199*bebae9c0SAndroid Build Coastguard Worker bufferId = *mAvailableBuffers.begin();
200*bebae9c0SAndroid Build Coastguard Worker CHECK_LT(bufferId, mBuffers.size());
201*bebae9c0SAndroid Build Coastguard Worker sp<IMemory> mem = mBuffers.itemAt(bufferId);
202*bebae9c0SAndroid Build Coastguard Worker bufferLoc = mem->unsecurePointer();
203*bebae9c0SAndroid Build Coastguard Worker buffSize = mem->size();
204*bebae9c0SAndroid Build Coastguard Worker
205*bebae9c0SAndroid Build Coastguard Worker char *pSrc = ((char*)oldFront->mDataBuffer) + oldFront->mDataSizeConsumed;
206*bebae9c0SAndroid Build Coastguard Worker if (oldFront->mDataSizeConsumed + buffSize < oldFront->mDataSize) {
207*bebae9c0SAndroid Build Coastguard Worker // more available than requested, copy as much as requested
208*bebae9c0SAndroid Build Coastguard Worker // consume data: 1/ copy to given destination
209*bebae9c0SAndroid Build Coastguard Worker memcpy(bufferLoc, pSrc, buffSize);
210*bebae9c0SAndroid Build Coastguard Worker // 2/ keep track of how much has been consumed
211*bebae9c0SAndroid Build Coastguard Worker oldFront->mDataSizeConsumed += buffSize;
212*bebae9c0SAndroid Build Coastguard Worker // 3/ notify shared mem listener that new data is available
213*bebae9c0SAndroid Build Coastguard Worker receivedBuffer_l(bufferId, buffSize);
214*bebae9c0SAndroid Build Coastguard Worker mAvailableBuffers.erase(mAvailableBuffers.begin());
215*bebae9c0SAndroid Build Coastguard Worker } else {
216*bebae9c0SAndroid Build Coastguard Worker // requested as much available or more: consume the whole of the current
217*bebae9c0SAndroid Build Coastguard Worker // buffer and move to the next
218*bebae9c0SAndroid Build Coastguard Worker size_t consumed = oldFront->mDataSize - oldFront->mDataSizeConsumed;
219*bebae9c0SAndroid Build Coastguard Worker //SL_LOGD("consuming rest of buffer: enqueueing=%u", consumed);
220*bebae9c0SAndroid Build Coastguard Worker oldFront->mDataSizeConsumed = oldFront->mDataSize;
221*bebae9c0SAndroid Build Coastguard Worker
222*bebae9c0SAndroid Build Coastguard Worker // move queue to next
223*bebae9c0SAndroid Build Coastguard Worker if (newFront == &mAndroidBufferQueue->
224*bebae9c0SAndroid Build Coastguard Worker mBufferArray[mAndroidBufferQueue->mNumBuffers + 1]) {
225*bebae9c0SAndroid Build Coastguard Worker // reached the end, circle back
226*bebae9c0SAndroid Build Coastguard Worker newFront = mAndroidBufferQueue->mBufferArray;
227*bebae9c0SAndroid Build Coastguard Worker }
228*bebae9c0SAndroid Build Coastguard Worker mAndroidBufferQueue->mFront = newFront;
229*bebae9c0SAndroid Build Coastguard Worker mAndroidBufferQueue->mState.count--;
230*bebae9c0SAndroid Build Coastguard Worker mAndroidBufferQueue->mState.index++;
231*bebae9c0SAndroid Build Coastguard Worker
232*bebae9c0SAndroid Build Coastguard Worker if (consumed > 0) {
233*bebae9c0SAndroid Build Coastguard Worker // consume data: 1/ copy to given destination
234*bebae9c0SAndroid Build Coastguard Worker memcpy(bufferLoc, pSrc, consumed);
235*bebae9c0SAndroid Build Coastguard Worker // 2/ keep track of how much has been consumed
236*bebae9c0SAndroid Build Coastguard Worker // here nothing to do because we are done with this buffer
237*bebae9c0SAndroid Build Coastguard Worker // 3/ notify StreamPlayer that new data is available
238*bebae9c0SAndroid Build Coastguard Worker receivedBuffer_l(bufferId, consumed);
239*bebae9c0SAndroid Build Coastguard Worker mAvailableBuffers.erase(mAvailableBuffers.begin());
240*bebae9c0SAndroid Build Coastguard Worker }
241*bebae9c0SAndroid Build Coastguard Worker
242*bebae9c0SAndroid Build Coastguard Worker // data has been consumed, and the buffer queue state has been updated
243*bebae9c0SAndroid Build Coastguard Worker // we will notify the client if applicable
244*bebae9c0SAndroid Build Coastguard Worker queueCallbackCandidate = true;
245*bebae9c0SAndroid Build Coastguard Worker }
246*bebae9c0SAndroid Build Coastguard Worker }
247*bebae9c0SAndroid Build Coastguard Worker
248*bebae9c0SAndroid Build Coastguard Worker if (queueCallbackCandidate) {
249*bebae9c0SAndroid Build Coastguard Worker if (mAndroidBufferQueue->mCallbackEventsMask &
250*bebae9c0SAndroid Build Coastguard Worker SL_ANDROIDBUFFERQUEUEEVENT_PROCESSED) {
251*bebae9c0SAndroid Build Coastguard Worker callback = mAndroidBufferQueue->mCallback;
252*bebae9c0SAndroid Build Coastguard Worker // save callback data while under lock
253*bebae9c0SAndroid Build Coastguard Worker callbackPContext = mAndroidBufferQueue->mContext;
254*bebae9c0SAndroid Build Coastguard Worker pBufferContext = (void *)oldFront->mBufferContext;
255*bebae9c0SAndroid Build Coastguard Worker pBufferData = (void *)oldFront->mDataBuffer;
256*bebae9c0SAndroid Build Coastguard Worker dataSize = oldFront->mDataSize;
257*bebae9c0SAndroid Build Coastguard Worker // here a buffer is only dequeued when fully consumed
258*bebae9c0SAndroid Build Coastguard Worker //dataUsed = oldFront->mDataSizeConsumed;
259*bebae9c0SAndroid Build Coastguard Worker }
260*bebae9c0SAndroid Build Coastguard Worker }
261*bebae9c0SAndroid Build Coastguard Worker //SL_LOGD("%d buffers available after reading from queue", mAvailableBuffers.size());
262*bebae9c0SAndroid Build Coastguard Worker if (!mAvailableBuffers.empty()) {
263*bebae9c0SAndroid Build Coastguard Worker // there is still room in the shared memory, recheck later if we can pull
264*bebae9c0SAndroid Build Coastguard Worker // data from the buffer queue and write it to shared memory
265*bebae9c0SAndroid Build Coastguard Worker const sp<StreamPlayer> player(mPlayer.promote());
266*bebae9c0SAndroid Build Coastguard Worker if (player != NULL) {
267*bebae9c0SAndroid Build Coastguard Worker player->queueRefilled();
268*bebae9c0SAndroid Build Coastguard Worker }
269*bebae9c0SAndroid Build Coastguard Worker }
270*bebae9c0SAndroid Build Coastguard Worker }
271*bebae9c0SAndroid Build Coastguard Worker
272*bebae9c0SAndroid Build Coastguard Worker } else { // empty queue
273*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("ABQ empty, starving!");
274*bebae9c0SAndroid Build Coastguard Worker }
275*bebae9c0SAndroid Build Coastguard Worker
276*bebae9c0SAndroid Build Coastguard Worker interface_unlock_exclusive(mAndroidBufferQueue);
277*bebae9c0SAndroid Build Coastguard Worker
278*bebae9c0SAndroid Build Coastguard Worker // notify client of buffer processed
279*bebae9c0SAndroid Build Coastguard Worker if (NULL != callback) {
280*bebae9c0SAndroid Build Coastguard Worker SLresult result = (*callback)(&mAndroidBufferQueue->mItf, callbackPContext,
281*bebae9c0SAndroid Build Coastguard Worker pBufferContext, pBufferData, dataSize,
282*bebae9c0SAndroid Build Coastguard Worker dataSize, /* dataUsed */
283*bebae9c0SAndroid Build Coastguard Worker // no messages during playback other than marking the buffer as processed
284*bebae9c0SAndroid Build Coastguard Worker (const SLAndroidBufferItem*)(&kItemProcessed) /* pItems */,
285*bebae9c0SAndroid Build Coastguard Worker NB_BUFFEREVENT_ITEM_FIELDS *sizeof(SLuint32) /* itemsLength */ );
286*bebae9c0SAndroid Build Coastguard Worker if (SL_RESULT_SUCCESS != result) {
287*bebae9c0SAndroid Build Coastguard Worker // Reserved for future use
288*bebae9c0SAndroid Build Coastguard Worker SL_LOGW("Unsuccessful result %d returned from AndroidBufferQueueCallback", result);
289*bebae9c0SAndroid Build Coastguard Worker }
290*bebae9c0SAndroid Build Coastguard Worker }
291*bebae9c0SAndroid Build Coastguard Worker
292*bebae9c0SAndroid Build Coastguard Worker mCallbackProtector->exitCb();
293*bebae9c0SAndroid Build Coastguard Worker } // enterCbIfOk
294*bebae9c0SAndroid Build Coastguard Worker }
295*bebae9c0SAndroid Build Coastguard Worker
296*bebae9c0SAndroid Build Coastguard Worker
297*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------------------------------------------------------
StreamPlayer(const AudioPlayback_Parameters * params,bool hasVideo,IAndroidBufferQueue * androidBufferQueue,const sp<CallbackProtector> & callbackProtector)298*bebae9c0SAndroid Build Coastguard Worker StreamPlayer::StreamPlayer(const AudioPlayback_Parameters* params, bool hasVideo,
299*bebae9c0SAndroid Build Coastguard Worker IAndroidBufferQueue *androidBufferQueue, const sp<CallbackProtector> &callbackProtector) :
300*bebae9c0SAndroid Build Coastguard Worker GenericMediaPlayer(params, hasVideo),
301*bebae9c0SAndroid Build Coastguard Worker mAppProxy(new StreamSourceAppProxy(androidBufferQueue, callbackProtector, this)),
302*bebae9c0SAndroid Build Coastguard Worker mStopForDestroyCompleted(false)
303*bebae9c0SAndroid Build Coastguard Worker {
304*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("StreamPlayer::StreamPlayer()");
305*bebae9c0SAndroid Build Coastguard Worker }
306*bebae9c0SAndroid Build Coastguard Worker
~StreamPlayer()307*bebae9c0SAndroid Build Coastguard Worker StreamPlayer::~StreamPlayer() {
308*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("StreamPlayer::~StreamPlayer()");
309*bebae9c0SAndroid Build Coastguard Worker mAppProxy->disconnect();
310*bebae9c0SAndroid Build Coastguard Worker }
311*bebae9c0SAndroid Build Coastguard Worker
312*bebae9c0SAndroid Build Coastguard Worker
onMessageReceived(const sp<AMessage> & msg)313*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::onMessageReceived(const sp<AMessage> &msg) {
314*bebae9c0SAndroid Build Coastguard Worker switch (msg->what()) {
315*bebae9c0SAndroid Build Coastguard Worker case kWhatPullFromAbq:
316*bebae9c0SAndroid Build Coastguard Worker onPullFromAndroidBufferQueue();
317*bebae9c0SAndroid Build Coastguard Worker break;
318*bebae9c0SAndroid Build Coastguard Worker
319*bebae9c0SAndroid Build Coastguard Worker case kWhatStopForDestroy:
320*bebae9c0SAndroid Build Coastguard Worker onStopForDestroy();
321*bebae9c0SAndroid Build Coastguard Worker break;
322*bebae9c0SAndroid Build Coastguard Worker
323*bebae9c0SAndroid Build Coastguard Worker default:
324*bebae9c0SAndroid Build Coastguard Worker GenericMediaPlayer::onMessageReceived(msg);
325*bebae9c0SAndroid Build Coastguard Worker break;
326*bebae9c0SAndroid Build Coastguard Worker }
327*bebae9c0SAndroid Build Coastguard Worker }
328*bebae9c0SAndroid Build Coastguard Worker
329*bebae9c0SAndroid Build Coastguard Worker
preDestroy()330*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::preDestroy() {
331*bebae9c0SAndroid Build Coastguard Worker // FIXME NuPlayerDriver is currently not thread-safe, so stop() must be called by looper
332*bebae9c0SAndroid Build Coastguard Worker (new AMessage(kWhatStopForDestroy, this))->post();
333*bebae9c0SAndroid Build Coastguard Worker {
334*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mStopForDestroyLock);
335*bebae9c0SAndroid Build Coastguard Worker while (!mStopForDestroyCompleted) {
336*bebae9c0SAndroid Build Coastguard Worker mStopForDestroyCondition.wait(mStopForDestroyLock);
337*bebae9c0SAndroid Build Coastguard Worker }
338*bebae9c0SAndroid Build Coastguard Worker }
339*bebae9c0SAndroid Build Coastguard Worker // GenericMediaPlayer::preDestroy will repeat some of what we've done, but that's benign
340*bebae9c0SAndroid Build Coastguard Worker GenericMediaPlayer::preDestroy();
341*bebae9c0SAndroid Build Coastguard Worker }
342*bebae9c0SAndroid Build Coastguard Worker
343*bebae9c0SAndroid Build Coastguard Worker
onStopForDestroy()344*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::onStopForDestroy() {
345*bebae9c0SAndroid Build Coastguard Worker if (mPlayer != 0) {
346*bebae9c0SAndroid Build Coastguard Worker mPlayer->stop();
347*bebae9c0SAndroid Build Coastguard Worker // causes CHECK failure in Nuplayer
348*bebae9c0SAndroid Build Coastguard Worker //mPlayer->setDataSource(NULL);
349*bebae9c0SAndroid Build Coastguard Worker mPlayer->setVideoSurfaceTexture(NULL);
350*bebae9c0SAndroid Build Coastguard Worker mPlayer->disconnect();
351*bebae9c0SAndroid Build Coastguard Worker mPlayer.clear();
352*bebae9c0SAndroid Build Coastguard Worker {
353*bebae9c0SAndroid Build Coastguard Worker // FIXME ugh make this a method
354*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mPreparedPlayerLock);
355*bebae9c0SAndroid Build Coastguard Worker mPreparedPlayer.clear();
356*bebae9c0SAndroid Build Coastguard Worker }
357*bebae9c0SAndroid Build Coastguard Worker }
358*bebae9c0SAndroid Build Coastguard Worker {
359*bebae9c0SAndroid Build Coastguard Worker Mutex::Autolock _l(mStopForDestroyLock);
360*bebae9c0SAndroid Build Coastguard Worker mStopForDestroyCompleted = true;
361*bebae9c0SAndroid Build Coastguard Worker }
362*bebae9c0SAndroid Build Coastguard Worker mStopForDestroyCondition.signal();
363*bebae9c0SAndroid Build Coastguard Worker }
364*bebae9c0SAndroid Build Coastguard Worker
365*bebae9c0SAndroid Build Coastguard Worker
366*bebae9c0SAndroid Build Coastguard Worker /**
367*bebae9c0SAndroid Build Coastguard Worker * Asynchronously notify the player that the queue is ready to be pulled from.
368*bebae9c0SAndroid Build Coastguard Worker */
queueRefilled()369*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::queueRefilled() {
370*bebae9c0SAndroid Build Coastguard Worker // async notification that the ABQ was refilled: the player should pull from the ABQ, and
371*bebae9c0SAndroid Build Coastguard Worker // and push to shared memory (to the media server)
372*bebae9c0SAndroid Build Coastguard Worker (new AMessage(kWhatPullFromAbq, this))->post();
373*bebae9c0SAndroid Build Coastguard Worker }
374*bebae9c0SAndroid Build Coastguard Worker
375*bebae9c0SAndroid Build Coastguard Worker
appClear_l()376*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::appClear_l() {
377*bebae9c0SAndroid Build Coastguard Worker // the user of StreamPlayer has cleared its AndroidBufferQueue:
378*bebae9c0SAndroid Build Coastguard Worker // there's no clear() for the shared memory queue, so this is a no-op
379*bebae9c0SAndroid Build Coastguard Worker }
380*bebae9c0SAndroid Build Coastguard Worker
381*bebae9c0SAndroid Build Coastguard Worker
382*bebae9c0SAndroid Build Coastguard Worker //--------------------------------------------------
383*bebae9c0SAndroid Build Coastguard Worker // Event handlers
onPrepare()384*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::onPrepare() {
385*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("StreamPlayer::onPrepare()");
386*bebae9c0SAndroid Build Coastguard Worker sp<IMediaPlayerService> mediaPlayerService(getMediaPlayerService());
387*bebae9c0SAndroid Build Coastguard Worker if (mediaPlayerService != NULL) {
388*bebae9c0SAndroid Build Coastguard Worker mPlayer = mediaPlayerService->create(mPlayerClient /*IMediaPlayerClient*/,
389*bebae9c0SAndroid Build Coastguard Worker mPlaybackParams.sessionId);
390*bebae9c0SAndroid Build Coastguard Worker if (mPlayer == NULL) {
391*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("media player service failed to create player by app proxy");
392*bebae9c0SAndroid Build Coastguard Worker } else if (mPlayer->setDataSource(static_cast<sp<IStreamSource>>(mAppProxy)) !=
393*bebae9c0SAndroid Build Coastguard Worker NO_ERROR) {
394*bebae9c0SAndroid Build Coastguard Worker SL_LOGE("setDataSource failed");
395*bebae9c0SAndroid Build Coastguard Worker mPlayer.clear();
396*bebae9c0SAndroid Build Coastguard Worker }
397*bebae9c0SAndroid Build Coastguard Worker }
398*bebae9c0SAndroid Build Coastguard Worker if (mPlayer == NULL) {
399*bebae9c0SAndroid Build Coastguard Worker mStateFlags |= kFlagPreparedUnsuccessfully;
400*bebae9c0SAndroid Build Coastguard Worker }
401*bebae9c0SAndroid Build Coastguard Worker GenericMediaPlayer::onPrepare();
402*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("StreamPlayer::onPrepare() done");
403*bebae9c0SAndroid Build Coastguard Worker }
404*bebae9c0SAndroid Build Coastguard Worker
405*bebae9c0SAndroid Build Coastguard Worker
onPlay()406*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::onPlay() {
407*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("StreamPlayer::onPlay()");
408*bebae9c0SAndroid Build Coastguard Worker // enqueue a message that will cause StreamAppProxy to consume from the queue (again if the
409*bebae9c0SAndroid Build Coastguard Worker // player had starved the shared memory)
410*bebae9c0SAndroid Build Coastguard Worker queueRefilled();
411*bebae9c0SAndroid Build Coastguard Worker
412*bebae9c0SAndroid Build Coastguard Worker GenericMediaPlayer::onPlay();
413*bebae9c0SAndroid Build Coastguard Worker }
414*bebae9c0SAndroid Build Coastguard Worker
415*bebae9c0SAndroid Build Coastguard Worker
onPullFromAndroidBufferQueue()416*bebae9c0SAndroid Build Coastguard Worker void StreamPlayer::onPullFromAndroidBufferQueue() {
417*bebae9c0SAndroid Build Coastguard Worker SL_LOGD("StreamPlayer::onPullFromAndroidBufferQueue()");
418*bebae9c0SAndroid Build Coastguard Worker mAppProxy->pullFromBuffQueue();
419*bebae9c0SAndroid Build Coastguard Worker }
420*bebae9c0SAndroid Build Coastguard Worker
421*bebae9c0SAndroid Build Coastguard Worker } // namespace android
422