android_StreamPlayer.cpp revision 13837cf3f7be0eb8b1a9552bd99a89f98c987720
1/*
2 * Copyright (C) 2010 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 USE_LOG SLAndroidLogLevel_Verbose
18
19#include "sles_allinclusive.h"
20#include <media/IMediaPlayerService.h>
21
22//--------------------------------------------------------------------------------------------------
23// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
24
25void android_StreamPlayer_realize_l(CAudioPlayer *ap, const notif_cbf_t cbf, void* notifUser) {
26    SL_LOGI("android_StreamPlayer_realize_l(%p)", ap);
27
28    AudioPlayback_Parameters ap_params;
29    ap_params.sessionId = ap->mSessionId;
30    ap_params.streamType = ap->mStreamType;
31    ap_params.trackcb = NULL;
32    ap_params.trackcbUser = NULL;
33    ap->mStreamPlayer = new android::StreamPlayer(&ap_params);
34    ap->mStreamPlayer->init(cbf, notifUser);
35}
36
37
38// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
39void android_StreamPlayer_destroy(CAudioPlayer *ap) {
40    SL_LOGI("android_StreamPlayer_destroy(%p)", ap);
41
42    ap->mStreamPlayer.clear();
43}
44
45
46//-----------------------------------------------------------------------------
47void android_StreamPlayer_androidBufferQueue_registerCallback(android::StreamPlayer *splr,
48        slAndroidBufferQueueCallback callback, void* context, const void* callerItf)
49{
50    if (splr != NULL) {
51        SL_LOGI("android_Player_androidBufferQueue_registerCallback");
52        splr->registerQueueCallback(callback, context, callerItf);
53    }
54}
55
56// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
57void android_StreamPlayer_enqueue_l(CAudioPlayer *ap,
58        SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData) {
59    if (ap->mStreamPlayer != 0) {
60        ap->mStreamPlayer->appEnqueue(bufferId, length, event, pData);
61    }
62}
63
64
65// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
66void android_StreamPlayer_clear_l(CAudioPlayer *ap) {
67    if (ap->mStreamPlayer != 0) {
68        ap->mStreamPlayer->appClear();
69    }
70}
71
72//--------------------------------------------------------------------------------------------------
73namespace android {
74
75StreamSourceAppProxy::StreamSourceAppProxy(
76        slAndroidBufferQueueCallback callback, void *context, const void *caller) :
77    mCallback(callback),
78    mAppContext(context),
79    mCaller(caller)
80{
81    SL_LOGI("StreamSourceAppProxy::StreamSourceAppProxy()");
82}
83
84StreamSourceAppProxy::~StreamSourceAppProxy() {
85    SL_LOGI("StreamSourceAppProxy::~StreamSourceAppProxy()");
86    mListener.clear();
87    mBuffers.clear();
88}
89
90//--------------------------------------------------
91// IStreamSource implementation
92void StreamSourceAppProxy::setListener(const sp<IStreamListener> &listener) {
93    Mutex::Autolock _l(mListenerLock);
94    mListener = listener;
95}
96
97void StreamSourceAppProxy::setBuffers(const Vector<sp<IMemory> > &buffers) {
98    mBuffers = buffers;
99}
100
101void StreamSourceAppProxy::onBufferAvailable(size_t index) {
102    SL_LOGD("StreamSourceAppProxy::onBufferAvailable(%d)", index);
103
104    CHECK_LT(index, mBuffers.size());
105    sp<IMemory> mem = mBuffers.itemAt(index);
106    SLAint64 length = (SLAint64) mem->size();
107
108    // FIXME PRIORITY1 needs to be called asynchronously, from AudioPlayer code after having
109    //   obtained under lock the callback function pointer and context
110    (*mCallback)((SLAndroidBufferQueueItf)mCaller,     /* SLAndroidBufferQueueItf self */
111            mAppContext,  /* void *pContext */
112            index,        /* SLuint32 bufferId */
113            length,       /*  SLAint64 bufferLength */
114            mem->pointer()/* void *pBufferDataLocation */
115    );
116}
117
118void StreamSourceAppProxy::receivedFromAppCommand(IStreamListener::Command cmd) {
119    Mutex::Autolock _l(mListenerLock);
120    if (mListener != 0) {
121        mListener->issueCommand(cmd, false /* synchronous */);
122    }
123}
124
125void StreamSourceAppProxy::receivedFromAppBuffer(size_t buffIndex, size_t buffLength) {
126    Mutex::Autolock _l(mListenerLock);
127    if (mListener != 0) {
128        mListener->queueBuffer(buffIndex, buffLength);
129    }
130}
131
132
133//--------------------------------------------------------------------------------------------------
134StreamPlayer::StreamPlayer(AudioPlayback_Parameters* params) : AVPlayer(params),
135    mAppProxy(0)
136{
137    SL_LOGI("StreamPlayer::StreamPlayer()");
138
139    mPlaybackParams = *params;
140
141}
142
143StreamPlayer::~StreamPlayer() {
144    SL_LOGI("StreamPlayer::~StreamPlayer()");
145
146    mAppProxy.clear();
147}
148
149
150void StreamPlayer::registerQueueCallback(slAndroidBufferQueueCallback callback, void *context,
151        const void *caller) {
152    SL_LOGI("StreamPlayer::registerQueueCallback");
153    Mutex::Autolock _l(mLock);
154
155    mAppProxy = new StreamSourceAppProxy(callback, context, caller);
156
157    CHECK(mAppProxy != 0);
158    SL_LOGI("StreamPlayer::registerQueueCallback end");
159}
160
161void StreamPlayer::appEnqueue(SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event,
162        void *pData) {
163    Mutex::Autolock _l(mLock);
164    if (mAppProxy != 0) {
165        if (event != SL_ANDROIDBUFFERQUEUE_EVENT_NONE) {
166            if (event & SL_ANDROIDBUFFERQUEUE_EVENT_DISCONTINUITY) {
167                mAppProxy->receivedFromAppCommand(IStreamListener::DISCONTINUITY);
168            }
169            if (event & SL_ANDROIDBUFFERQUEUE_EVENT_EOS) {
170                mAppProxy->receivedFromAppCommand(IStreamListener::EOS);
171            }
172        }
173        if (length > 0) {
174            // FIXME PRIORITY1 verify given length isn't bigger than declared length in app callback
175            mAppProxy->receivedFromAppBuffer((size_t)bufferId, (size_t)length);
176        }
177    }
178}
179
180void StreamPlayer::appClear() {
181    Mutex::Autolock _l(mLock);
182    if (mAppProxy != 0) {
183        // FIXME PRIORITY1 implement
184        SL_LOGE("[ FIXME implement StreamPlayer::appClear() ]");
185    }
186}
187
188
189//--------------------------------------------------
190// Event handlers
191void StreamPlayer::onPrepare() {
192    SL_LOGI("StreamPlayer::onPrepare()");
193    //Mutex::Autolock _l(mLock);
194    if (mAppProxy != 0) {
195        mPlayer = mMediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/,
196                mAppProxy /*IStreamSource*/, mPlaybackParams.sessionId);
197        // blocks until mPlayer is prepared
198        AVPlayer::onPrepare();
199        SL_LOGI("StreamPlayer::onPrepare() done");
200    } else {
201        SL_LOGE("Nothing to do here because there is no registered callback");
202    }
203}
204
205
206
207} // namespace android
208