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