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