blob: 41b3dddf6e8f860f51dc8c6583ed832e57c4b048 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define USE_LOG SLAndroidLogLevel_Verbose
#include "sles_allinclusive.h"
#include <media/IMediaPlayerService.h>
//--------------------------------------------------------------------------------------------------
// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
void android_StreamPlayer_realize_l(CAudioPlayer *ap, const notif_cbf_t cbf, void* notifUser) {
SL_LOGI("android_StreamPlayer_realize_l(%p)", ap);
AudioPlayback_Parameters ap_params;
ap_params.sessionId = ap->mSessionId;
ap_params.streamType = ap->mStreamType;
ap_params.trackcb = NULL;
ap_params.trackcbUser = NULL;
ap->mStreamPlayer = new android::StreamPlayer(&ap_params, false /*hasVideo*/);
ap->mStreamPlayer->init(cbf, notifUser);
}
// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
void android_StreamPlayer_destroy(CAudioPlayer *ap) {
SL_LOGI("android_StreamPlayer_destroy(%p)", ap);
ap->mStreamPlayer.clear();
}
//-----------------------------------------------------------------------------
void android_StreamPlayer_androidBufferQueue_registerCallback(android::StreamPlayer *splr,
slAndroidBufferQueueCallback callback, void* context, const void* callerItf)
{
if (splr != NULL) {
SL_LOGI("android_Player_androidBufferQueue_registerCallback");
splr->registerQueueCallback(callback, context, callerItf);
}
}
// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
void android_StreamPlayer_enqueue_l(CAudioPlayer *ap,
SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event, void *pData) {
if (ap->mStreamPlayer != 0) {
ap->mStreamPlayer->appEnqueue(bufferId, length, event, pData);
}
}
// FIXME abstract out the diff between CMediaPlayer and CAudioPlayer
void android_StreamPlayer_clear_l(CAudioPlayer *ap) {
if (ap->mStreamPlayer != 0) {
ap->mStreamPlayer->appClear();
}
}
//--------------------------------------------------------------------------------------------------
namespace android {
StreamSourceAppProxy::StreamSourceAppProxy(
slAndroidBufferQueueCallback callback, void *context, const void *caller) :
mCallback(callback),
mAppContext(context),
mCaller(caller)
{
SL_LOGI("StreamSourceAppProxy::StreamSourceAppProxy()");
}
StreamSourceAppProxy::~StreamSourceAppProxy() {
SL_LOGI("StreamSourceAppProxy::~StreamSourceAppProxy()");
mListener.clear();
mBuffers.clear();
}
//--------------------------------------------------
// IStreamSource implementation
void StreamSourceAppProxy::setListener(const sp<IStreamListener> &listener) {
Mutex::Autolock _l(mListenerLock);
mListener = listener;
}
void StreamSourceAppProxy::setBuffers(const Vector<sp<IMemory> > &buffers) {
mBuffers = buffers;
}
void StreamSourceAppProxy::onBufferAvailable(size_t index) {
SL_LOGD("StreamSourceAppProxy::onBufferAvailable(%d)", index);
CHECK_LT(index, mBuffers.size());
sp<IMemory> mem = mBuffers.itemAt(index);
SLAint64 length = (SLAint64) mem->size();
// FIXME PRIORITY1 needs to be called asynchronously, from AudioPlayer code after having
// obtained under lock the callback function pointer and context
(*mCallback)((SLAndroidBufferQueueItf)mCaller, /* SLAndroidBufferQueueItf self */
mAppContext, /* void *pContext */
index, /* SLuint32 bufferId */
length, /* SLAint64 bufferLength */
mem->pointer()/* void *pBufferDataLocation */
);
}
void StreamSourceAppProxy::receivedFromAppCommand(IStreamListener::Command cmd) {
Mutex::Autolock _l(mListenerLock);
if (mListener != 0) {
mListener->issueCommand(cmd, false /* synchronous */);
}
}
void StreamSourceAppProxy::receivedFromAppBuffer(size_t buffIndex, size_t buffLength) {
Mutex::Autolock _l(mListenerLock);
if (mListener != 0) {
mListener->queueBuffer(buffIndex, buffLength);
}
}
//--------------------------------------------------------------------------------------------------
StreamPlayer::StreamPlayer(AudioPlayback_Parameters* params, bool hasVideo) :
GenericMediaPlayer(params, hasVideo),
mAppProxy(0)
{
SL_LOGI("StreamPlayer::StreamPlayer()");
mPlaybackParams = *params;
}
StreamPlayer::~StreamPlayer() {
SL_LOGI("StreamPlayer::~StreamPlayer()");
mAppProxy.clear();
}
void StreamPlayer::registerQueueCallback(slAndroidBufferQueueCallback callback, void *context,
const void *caller) {
SL_LOGI("StreamPlayer::registerQueueCallback");
Mutex::Autolock _l(mAppProxyLock);
mAppProxy = new StreamSourceAppProxy(callback, context, caller);
CHECK(mAppProxy != 0);
SL_LOGI("StreamPlayer::registerQueueCallback end");
}
void StreamPlayer::appEnqueue(SLuint32 bufferId, SLuint32 length, SLAbufferQueueEvent event,
void *pData) {
Mutex::Autolock _l(mAppProxyLock);
if (mAppProxy != 0) {
if (event != SL_ANDROIDBUFFERQUEUE_EVENT_NONE) {
if (event & SL_ANDROIDBUFFERQUEUE_EVENT_DISCONTINUITY) {
mAppProxy->receivedFromAppCommand(IStreamListener::DISCONTINUITY);
}
if (event & SL_ANDROIDBUFFERQUEUE_EVENT_EOS) {
mAppProxy->receivedFromAppCommand(IStreamListener::EOS);
}
}
if (length > 0) {
// FIXME PRIORITY1 verify given length isn't bigger than declared length in app callback
mAppProxy->receivedFromAppBuffer((size_t)bufferId, (size_t)length);
}
}
}
void StreamPlayer::appClear() {
Mutex::Autolock _l(mAppProxyLock);
if (mAppProxy != 0) {
// FIXME PRIORITY1 implement
SL_LOGE("[ FIXME implement StreamPlayer::appClear() ]");
}
}
//--------------------------------------------------
// Event handlers
void StreamPlayer::onPrepare() {
SL_LOGI("StreamPlayer::onPrepare()");
Mutex::Autolock _l(mAppProxyLock);
if (mAppProxy != 0) {
mPlayer = mMediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/,
mAppProxy /*IStreamSource*/, mPlaybackParams.sessionId);
// blocks until mPlayer is prepared
GenericMediaPlayer::onPrepare();
SL_LOGI("StreamPlayer::onPrepare() done");
} else {
SL_LOGE("Nothing to do here because there is no registered callback");
}
}
} // namespace android