OpenMAX AL: support URI and FD as data sources for MediaPlayer
Add ANDROIDFD as a data locator in OpenMAX AL
Implement playback of URI and FD in the LocAVPlayer class, that
inherits from AVPlayer
Fix bug where Android MediaPlayer resources were not destroyed
when the MediaPlayer object was destroyed.
Share URI and FD internal type definitions between SL and AL
Change-Id: I01d0d170baea4961f09b44339c99a79feba4620d
diff --git a/opensles/include/OMXAL/OpenMAXAL_Android.h b/opensles/include/OMXAL/OpenMAXAL_Android.h
index 1e4afe7..479da19 100644
--- a/opensles/include/OMXAL/OpenMAXAL_Android.h
+++ b/opensles/include/OMXAL/OpenMAXAL_Android.h
@@ -25,6 +25,8 @@
/* Android common types */
/*---------------------------------------------------------------------------*/
+typedef xa_int64_t XAAint64; /* 64 bit signed integer */
+
typedef XAuint32 XAAbufferQueueEvent;
/*---------------------------------------------------------------------------*/
@@ -127,6 +129,24 @@
XAuint32 queueSize; // FIXME ignored for now, subject to change
} XADataLocator_AndroidBufferQueue;
+
+/*---------------------------------------------------------------------------*/
+/* Android File Descriptor Data Locator */
+/*---------------------------------------------------------------------------*/
+
+/** Addendum to Data locator macros */
+#define XA_DATALOCATOR_ANDROIDFD ((SLuint32) 0x800007BC)
+
+#define XA_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE ((SLAint64) 0xFFFFFFFFFFFFFFFFll)
+
+/** File Descriptor-based data locator definition, locatorType must be XA_DATALOCATOR_ANDROIDFD */
+typedef struct XADataLocator_AndroidFD_ {
+ XAuint32 locatorType;
+ XAint32 fd;
+ XAAint64 offset;
+ XAAint64 length;
+} XADataLocator_AndroidFD;
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/opensles/libopensles/Android.mk b/opensles/libopensles/Android.mk
index 9890ce0..8721cee 100644
--- a/opensles/libopensles/Android.mk
+++ b/opensles/libopensles/Android.mk
@@ -58,6 +58,7 @@
android_AVPlayer.cpp \
android_AudioPlayer.cpp \
android_AudioRecorder.cpp \
+ android_LocAVPlayer.cpp \
android_OutputMix.cpp \
android_StreamPlayer.cpp \
android_SfPlayer.cpp \
diff --git a/opensles/libopensles/CMediaPlayer.c b/opensles/libopensles/CMediaPlayer.c
index 644e3e3..fd8b98c 100644
--- a/opensles/libopensles/CMediaPlayer.c
+++ b/opensles/libopensles/CMediaPlayer.c
@@ -86,6 +86,9 @@
freeDataLocatorFormat(&this->mImageVideoSink);
freeDataLocatorFormat(&this->mVibraSink);
freeDataLocatorFormat(&this->mLEDArraySink);
+#ifdef ANDROID
+ android_Player_destroy(this);
+#endif
}
diff --git a/opensles/libopensles/android_AVPlayer.cpp b/opensles/libopensles/android_AVPlayer.cpp
index 28b6e44..566f24b 100644
--- a/opensles/libopensles/android_AVPlayer.cpp
+++ b/opensles/libopensles/android_AVPlayer.cpp
@@ -59,6 +59,7 @@
mNotifyClient(NULL),
mNotifyUser(NULL),
mStateFlags(0),
+ mPlaybackParams(*params),
mVideoSurface(0),
mPlayer(0),
mPlayerClient(0)
@@ -67,8 +68,6 @@
mLooper = new android::ALooper();
- mPlaybackParams = *params;
-
mServiceManager = defaultServiceManager();
mBinder = mServiceManager->getService(String16("media.player"));
mMediaPlayerService = interface_cast<IMediaPlayerService>(mBinder);
diff --git a/opensles/libopensles/android_AudioPlayer.cpp b/opensles/libopensles/android_AudioPlayer.cpp
index 5df4928..6c219fb 100644
--- a/opensles/libopensles/android_AudioPlayer.cpp
+++ b/opensles/libopensles/android_AudioPlayer.cpp
@@ -1093,7 +1093,7 @@
pAudioPlayer->mSfPlayer->setDataSource(
(int)pAudioPlayer->mDataSource.mLocator.mFD.fd,
offset == SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE ?
- (int64_t)SFPLAYER_FD_FIND_FILE_SIZE : offset,
+ (int64_t)PLAYER_FD_FIND_FILE_SIZE : offset,
(int64_t)pAudioPlayer->mDataSource.mLocator.mFD.length);
} break;
default:
diff --git a/opensles/libopensles/android_LocAVPlayer.cpp b/opensles/libopensles/android_LocAVPlayer.cpp
new file mode 100644
index 0000000..544da57
--- /dev/null
+++ b/opensles/libopensles/android_LocAVPlayer.cpp
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 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"
+#undef this // FIXME shouldn't have to do this, no pun intended
+#include <media/IMediaPlayerService.h>
+
+
+namespace android {
+
+//--------------------------------------------------------------------------------------------------
+LocAVPlayer::LocAVPlayer(AudioPlayback_Parameters* params) : AVPlayer(params),
+ mDataLocatorType(kDataLocatorNone)
+{
+ SL_LOGI("LocAVPlayer::LocAVPlayer()");
+
+}
+
+
+LocAVPlayer::~LocAVPlayer() {
+ SL_LOGI("LocAVPlayer::~LocAVPlayer()");
+
+ resetDataLocator();
+}
+
+
+//--------------------------------------------------
+// Event handlers
+void LocAVPlayer::onPrepare() {
+ SL_LOGI("LocAVPlayer::onPrepare()");
+ Mutex::Autolock _l(mLock);
+ switch (mDataLocatorType) {
+ case kDataLocatorUri:
+ mPlayer = mMediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/,
+ mDataLocator.uri /*url*/, NULL /*headers*/, mPlaybackParams.sessionId);
+ break;
+ case kDataLocatorFd:
+ mPlayer = mMediaPlayerService->create(getpid(), mPlayerClient /*IMediaPlayerClient*/,
+ mDataLocator.fdi.fd, mDataLocator.fdi.offset, mDataLocator.fdi.length,
+ mPlaybackParams.sessionId);
+ break;
+ case kDataLocatorNone:
+ SL_LOGE("no data locator for MediaPlayer object");
+ break;
+ default:
+ SL_LOGE("unsupported data locator %d for MediaPlayer object", mDataLocatorType);
+ break;
+ }
+ // blocks until mPlayer is prepared
+ AVPlayer::onPrepare();
+ SL_LOGI("LocAVPlayer::onPrepare() done");
+}
+
+
+//--------------------------------------------------
+/*
+ * post-condition: mDataLocatorType == kDataLocatorNone
+ *
+ */
+void LocAVPlayer::resetDataLocator() {
+ if (kDataLocatorUri == mDataLocatorType) {
+ if (NULL != mDataLocator.uri) {
+ free(mDataLocator.uri);
+ mDataLocator.uri = NULL;
+ }
+ }
+ mDataLocatorType = kDataLocatorNone;
+}
+
+
+void LocAVPlayer::setDataSource(const char *uri) {
+ resetDataLocator();
+
+ // FIXME: a copy of the URI has already been made and is guaranteed to exist
+ // as long as the SLES/OMXAL object exists, so the copy here is not necessary
+ size_t len = strlen((const char *) uri);
+ char* newUri = (char*) malloc(len + 1);
+ if (NULL == newUri) {
+ // mem issue
+ SL_LOGE("LocAVPlayer::setDataSource: not enough memory to allocator URI string");
+ return;
+ }
+ memcpy(newUri, uri, len + 1);
+ mDataLocator.uri = newUri;
+
+ mDataLocatorType = kDataLocatorUri;
+}
+
+
+void LocAVPlayer::setDataSource(const int fd, const int64_t offset, const int64_t length) {
+ resetDataLocator();
+
+ mDataLocator.fdi.fd = fd;
+
+ struct stat sb;
+ int ret = fstat(fd, &sb);
+ if (ret != 0) {
+ SL_LOGE("LocAVPlayer::setDataSource: fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
+ return;
+ }
+
+ if (offset >= sb.st_size) {
+ SL_LOGE("SfPlayer::setDataSource: invalid offset");
+ return;
+ }
+ mDataLocator.fdi.offset = offset;
+
+ if (PLAYER_FD_FIND_FILE_SIZE == length) {
+ mDataLocator.fdi.length = sb.st_size;
+ } else if (offset + length > sb.st_size) {
+ mDataLocator.fdi.length = sb.st_size - offset;
+ } else {
+ mDataLocator.fdi.length = length;
+ }
+
+ mDataLocatorType = kDataLocatorFd;
+}
+
+} // namespace android
diff --git a/opensles/libopensles/android_LocAVPlayer.h b/opensles/libopensles/android_LocAVPlayer.h
new file mode 100644
index 0000000..fbbfaa8
--- /dev/null
+++ b/opensles/libopensles/android_LocAVPlayer.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+
+namespace android {
+
+//--------------------------------------------------------------------------------------------------
+class LocAVPlayer : public AVPlayer
+{
+public:
+ LocAVPlayer(AudioPlayback_Parameters* params);
+ virtual ~LocAVPlayer();
+
+ void setDataSource(const char *uri);
+ void setDataSource(const int fd, const int64_t offset, const int64_t length);
+
+protected:
+ // overridden from AVPlayer
+ virtual void onPrepare();
+
+ void resetDataLocator();
+ DataLocator mDataLocator;
+ int mDataLocatorType;
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(LocAVPlayer);
+};
+
+} // namespace android
diff --git a/opensles/libopensles/android_Player.cpp b/opensles/libopensles/android_Player.cpp
index cdff708..37d917a 100644
--- a/opensles/libopensles/android_Player.cpp
+++ b/opensles/libopensles/android_Player.cpp
@@ -59,20 +59,21 @@
// FIXME verify image data sink
const SLDataSink *pVideoSnk = &mp->mImageVideoSink.u.mSink;
- SLuint32 sourceLocator = *(SLuint32 *)pDataSrc->pLocator;
+ XAuint32 sourceLocator = *(XAuint32 *)pDataSrc->pLocator;
switch(sourceLocator) {
- // FIXME This should be Android simple buffer queue
+ // FIXME support Android simple buffer queue as well
case XA_DATALOCATOR_ANDROIDBUFFERQUEUE:
mp->mAndroidObjType = AV_PLR_TS_ABQ;
break;
case XA_DATALOCATOR_URI: // intended fall-through
+ case SL_DATALOCATOR_ANDROIDFD:
+ mp->mAndroidObjType = AV_PLR_URI_FD;
+ break;
case XA_DATALOCATOR_ADDRESS: // intended fall-through
- case SL_DATALOCATOR_ANDROIDFD: // intended fall-through
default:
SL_LOGE("Unable to create MediaPlayer for data source locator 0x%lx", sourceLocator);
result = XA_RESULT_PARAMETER_INVALID;
break;
-
}
mp->mAndroidObjState = ANDROID_UNINITIALIZED;
@@ -111,6 +112,30 @@
mp->mAVPlayer->init(player_handleMediaPlayerEventNotifications, (void*)mp);
}
break;
+ case AV_PLR_URI_FD: {
+ mp->mAVPlayer = new android::LocAVPlayer(&ap_params);
+ mp->mAVPlayer->init(player_handleMediaPlayerEventNotifications, (void*)mp);
+ switch (mp->mDataSource.mLocator.mLocatorType) {
+ case XA_DATALOCATOR_URI:
+ ((android::LocAVPlayer*)mp->mAVPlayer.get())->setDataSource(
+ (const char*)mp->mDataSource.mLocator.mURI.URI);
+ break;
+ case XA_DATALOCATOR_ANDROIDFD: {
+ int64_t offset = (int64_t)mp->mDataSource.mLocator.mFD.offset;
+ ((android::LocAVPlayer*)mp->mAVPlayer.get())->setDataSource(
+ (int)mp->mDataSource.mLocator.mFD.fd,
+ offset == SL_DATALOCATOR_ANDROIDFD_USE_FILE_SIZE ?
+ (int64_t)PLAYER_FD_FIND_FILE_SIZE : offset,
+ (int64_t)mp->mDataSource.mLocator.mFD.length);
+ }
+ break;
+ default:
+ SL_LOGE("Invalid or unsupported data locator type %lu for data source",
+ mp->mDataSource.mLocator.mLocatorType);
+ result = XA_RESULT_PARAMETER_INVALID;
+ }
+ }
+ break;
case INVALID_TYPE: // intended fall-through
default:
SL_LOGE("Unable to realize MediaPlayer, invalid internal Android object type");
@@ -121,6 +146,17 @@
return result;
}
+//-----------------------------------------------------------------------------
+XAresult android_Player_destroy(CMediaPlayer *mp) {
+ SL_LOGI("android_Player_destroy(%p)", mp);
+ XAresult result = XA_RESULT_SUCCESS;
+
+ if (mp->mAVPlayer != 0) {
+ mp->mAVPlayer.clear();
+ }
+
+ return result;
+}
//-----------------------------------------------------------------------------
/**
@@ -149,7 +185,8 @@
case SL_PLAYSTATE_STOPPED: {
SL_LOGV("setting AVPlayer to SL_PLAYSTATE_STOPPED");
avp->stop();
- } break;
+ }
+ break;
case SL_PLAYSTATE_PAUSED: {
SL_LOGV("setting AVPlayer to SL_PLAYSTATE_PAUSED");
switch(objState) {
@@ -166,7 +203,8 @@
SL_LOGE("Android object in invalid state");
break;
}
- } break;
+ }
+ break;
case SL_PLAYSTATE_PLAYING: {
SL_LOGV("setting AVPlayer to SL_PLAYSTATE_PLAYING");
switch(objState) {
@@ -183,8 +221,8 @@
SL_LOGE("Android object in invalid state");
break;
}
- } break;
-
+ }
+ break;
default:
// checked by caller, should not happen
break;
diff --git a/opensles/libopensles/android_Player.h b/opensles/libopensles/android_Player.h
index 4a1bb33..c777d0c 100644
--- a/opensles/libopensles/android_Player.h
+++ b/opensles/libopensles/android_Player.h
@@ -22,6 +22,8 @@
extern XAresult android_Player_realize(CMediaPlayer *mp, SLboolean async);
+extern XAresult android_Player_destroy(CMediaPlayer *mp);
+
/**************************************************************************************************
* Configuration
diff --git a/opensles/libopensles/android_SfPlayer.cpp b/opensles/libopensles/android_SfPlayer.cpp
index ac95b31..a8751e5 100644
--- a/opensles/libopensles/android_SfPlayer.cpp
+++ b/opensles/libopensles/android_SfPlayer.cpp
@@ -165,7 +165,7 @@
}
mDataLocator.fdi.offset = offset;
- if (SFPLAYER_FD_FIND_FILE_SIZE == length) {
+ if (PLAYER_FD_FIND_FILE_SIZE == length) {
mDataLocator.fdi.length = sb.st_size;
} else if (offset + length > sb.st_size) {
mDataLocator.fdi.length = sb.st_size - offset;
diff --git a/opensles/libopensles/android_SfPlayer.h b/opensles/libopensles/android_SfPlayer.h
index a040bee..3baa4a4 100644
--- a/opensles/libopensles/android_SfPlayer.h
+++ b/opensles/libopensles/android_SfPlayer.h
@@ -50,8 +50,6 @@
#define SIZE_CACHED_LOW_BYTES 400000
-#define SFPLAYER_FD_FIND_FILE_SIZE ((int64_t)0xFFFFFFFFFFFFFFFFll)
-
#define NO_FILL_LEVEL_UPDATE -1
#define NO_STATUS_UPDATE kStatusUnknown
@@ -120,12 +118,6 @@
private:
enum {
- kDataLocatorNone = 'none',
- kDataLocatorUri = 'uri',
- kDataLocatorFd = 'fd',
- };
-
- enum {
kWhatPrepare = 'prep',
kWhatDecode = 'deco',
kWhatRender = 'rend',
@@ -145,16 +137,6 @@
kFlagLooping = 16,
};
- struct FdInfo {
- int fd;
- int64_t offset;
- int64_t length;
- };
-
- union DataLocator {
- char* uri;
- FdInfo fdi;
- };
#ifdef _DEBUG_AUDIO_TESTS
FILE *mMonitorAudioFp; // Automated tests
#endif
diff --git a/opensles/libopensles/android_StreamPlayer.h b/opensles/libopensles/android_StreamPlayer.h
index 79ee7ca..d4d792b 100644
--- a/opensles/libopensles/android_StreamPlayer.h
+++ b/opensles/libopensles/android_StreamPlayer.h
@@ -17,12 +17,6 @@
#include <binder/IServiceManager.h>
-typedef struct StreamPlayback_Parameters_struct {
- int streamType;
- int sessionId;
-} StreamPlayback_Parameters;
-
-
//--------------------------------------------------------------------------------------------------
namespace android {
diff --git a/opensles/libopensles/android_defs.h b/opensles/libopensles/android_defs.h
index 016d9e2..89bab0f 100644
--- a/opensles/libopensles/android_defs.h
+++ b/opensles/libopensles/android_defs.h
@@ -25,6 +25,7 @@
A_PLR_PCM_BQ = 1, // audio player, PCM, buffer queue data source
A_PLR_TS_ABQ = 2, // audio player, transport stream, Android buffer queue data source
AV_PLR_TS_ABQ = 3, // audio video player, transport stream, Android buffer queue data source
+ AV_PLR_URI_FD = 4, // audio video player, compressed data, URI or FD data source
NUM_AUDIOPLAYER_MAP_TYPES
};
@@ -45,6 +46,8 @@
#define PLAYER_SUCCESS 1
+#define PLAYER_FD_FIND_FILE_SIZE ((int64_t)0xFFFFFFFFFFFFFFFFll)
+
/*
* Structure to maintain the set of audio levels about a player
@@ -67,8 +70,6 @@
} AndroidAudioLevels;
-
-
typedef void (*notif_client_t)(int event, const int data1, void* notifUser);
@@ -80,3 +81,25 @@
#define PLAYEREVENT_PREFETCHFILLLEVELUPDATE "pflu"
#define PLAYEREVENT_ENDOFSTREAM "eos"
#define PLAYEREVENT_NEW_AUDIOTRACK "nwat"
+
+
+namespace android {
+
+enum {
+ kDataLocatorNone = 'none',
+ kDataLocatorUri = 'uri',
+ kDataLocatorFd = 'fd',
+ };
+
+struct FdInfo {
+ int fd;
+ int64_t offset;
+ int64_t length;
+};
+
+union DataLocator {
+ char* uri;
+ FdInfo fdi;
+};
+
+} // namespace android
diff --git a/opensles/libopensles/sles_allinclusive.h b/opensles/libopensles/sles_allinclusive.h
index 5bff541..1464f74 100644
--- a/opensles/libopensles/sles_allinclusive.h
+++ b/opensles/libopensles/sles_allinclusive.h
@@ -263,6 +263,7 @@
#include "android_Effect.h"
#include "android_AVPlayer.h"
#include "android_StreamPlayer.h"
+#include "android_LocAVPlayer.h"
#endif
#endif // ANDROID