summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Grossman <johngro@google.com>2012-06-21 17:29:24 -0700
committerJohn Grossman <johngro@google.com>2012-08-13 09:48:56 -0700
commit44a7e42f0310831e6a846d1b6bb40bf3a399bf6d (patch)
treeaba58d779eb8a1d8fe4616d33b8eb6e1672d6f00
parentb3e12a4d15a329821979bf287c49a9630486e23f (diff)
downloadframeworks_av-44a7e42f0310831e6a846d1b6bb40bf3a399bf6d.zip
frameworks_av-44a7e42f0310831e6a846d1b6bb40bf3a399bf6d.tar.gz
frameworks_av-44a7e42f0310831e6a846d1b6bb40bf3a399bf6d.tar.bz2
Add the ability to dynamicaly register MediaPlayer types.
Add the ability to dynamically register low level MediaPlayer factories which will be probed at setDataSource time to determine the proper MediaPlayerBase to instantiate. This change is in preparation for moving libaah_rtp out of frameworks/base and into phantasm platform directory. Change-Id: Icf8904db3ab9e3c85df6e780d5546d9988cb9076 Signed-off-by: John Grossman <johngro@google.com>
-rw-r--r--include/media/IMediaPlayer.h1
-rw-r--r--include/media/MediaPlayerInterface.h7
-rw-r--r--media/libmedia/IMediaPlayer.cpp34
-rw-r--r--media/libmediaplayerservice/Android.mk1
-rw-r--r--media/libmediaplayerservice/MediaPlayerFactory.cpp404
-rw-r--r--media/libmediaplayerservice/MediaPlayerFactory.h84
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp241
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h6
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp22
9 files changed, 583 insertions, 217 deletions
diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h
index 00facc5..4ed1863 100644
--- a/include/media/IMediaPlayer.h
+++ b/include/media/IMediaPlayer.h
@@ -64,6 +64,7 @@ public:
virtual status_t setParameter(int key, const Parcel& request) = 0;
virtual status_t getParameter(int key, Parcel* reply) = 0;
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) = 0;
+ virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) = 0;
virtual status_t setNextPlayer(const sp<IMediaPlayer>& next) = 0;
// Invoke a generic method on the player by using opaque parcels
diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h
index a70fe8c..0498ed1 100644
--- a/include/media/MediaPlayerInterface.h
+++ b/include/media/MediaPlayerInterface.h
@@ -154,12 +154,15 @@ public:
virtual status_t getParameter(int key, Parcel *reply) = 0;
// Right now, only the AAX TX player supports this functionality. For now,
- // provide a default implementation which indicates a lack of support for
- // this functionality to make life easier for all of the other media player
+ // provide default implementations which indicate a lack of support for this
+ // functionality to make life easier for all of the other media player
// maintainers out there.
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
return INVALID_OPERATION;
}
+ virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint) {
+ return INVALID_OPERATION;
+ }
// Invoke a generic method on the player by using opaque parcels
// for the request and reply.
diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp
index 0bb237d..cb07766 100644
--- a/media/libmedia/IMediaPlayer.cpp
+++ b/media/libmedia/IMediaPlayer.cpp
@@ -55,6 +55,7 @@ enum {
SET_PARAMETER,
GET_PARAMETER,
SET_RETRANSMIT_ENDPOINT,
+ GET_RETRANSMIT_ENDPOINT,
SET_NEXT_PLAYER,
};
@@ -292,7 +293,8 @@ public:
return remote()->transact(GET_PARAMETER, data, reply);
}
- status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint) {
+ status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint)
+ {
Parcel data, reply;
status_t err;
@@ -319,6 +321,23 @@ public:
remote()->transact(SET_NEXT_PLAYER, data, &reply);
return reply.readInt32();
}
+
+ status_t getRetransmitEndpoint(struct sockaddr_in* endpoint)
+ {
+ Parcel data, reply;
+ status_t err;
+
+ data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
+ err = remote()->transact(GET_RETRANSMIT_ENDPOINT, data, &reply);
+
+ if ((OK != err) || (OK != (err = reply.readInt32()))) {
+ return err;
+ }
+
+ data.read(endpoint, sizeof(*endpoint));
+
+ return err;
+ }
};
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
@@ -498,11 +517,24 @@ status_t BnMediaPlayer::onTransact(
} else {
reply->writeInt32(setRetransmitEndpoint(NULL));
}
+
+ return NO_ERROR;
+ } break;
+ case GET_RETRANSMIT_ENDPOINT: {
+ CHECK_INTERFACE(IMediaPlayer, data, reply);
+
+ struct sockaddr_in endpoint;
+ status_t res = getRetransmitEndpoint(&endpoint);
+
+ reply->writeInt32(res);
+ reply->write(&endpoint, sizeof(endpoint));
+
return NO_ERROR;
} break;
case SET_NEXT_PLAYER: {
CHECK_INTERFACE(IMediaPlayer, data, reply);
reply->writeInt32(setNextPlayer(interface_cast<IMediaPlayer>(data.readStrongBinder())));
+
return NO_ERROR;
} break;
default:
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index f173e2e..e3134d1 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -10,6 +10,7 @@ LOCAL_SRC_FILES:= \
ActivityManager.cpp \
Crypto.cpp \
MediaRecorderClient.cpp \
+ MediaPlayerFactory.cpp \
MediaPlayerService.cpp \
MetadataRetrieverClient.cpp \
TestPlayerStub.cpp \
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp
new file mode 100644
index 0000000..dcb347f
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp
@@ -0,0 +1,404 @@
+/*
+**
+** Copyright 2012, 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 LOG_TAG "MediaPlayerFactory"
+#include <utils/Log.h>
+
+#include <cutils/properties.h>
+#include <media/IMediaPlayer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <utils/Errors.h>
+#include <utils/misc.h>
+
+#include "MediaPlayerFactory.h"
+
+#include "MidiFile.h"
+#include "TestPlayerStub.h"
+#include "StagefrightPlayer.h"
+#include "nuplayer/NuPlayerDriver.h"
+
+namespace android {
+
+extern sp<MediaPlayerBase> createAAH_TXPlayer();
+extern sp<MediaPlayerBase> createAAH_RXPlayer();
+
+Mutex MediaPlayerFactory::sLock;
+MediaPlayerFactory::tFactoryMap MediaPlayerFactory::sFactoryMap;
+bool MediaPlayerFactory::sInitComplete = false;
+
+status_t MediaPlayerFactory::registerFactory_l(IFactory* factory,
+ player_type type) {
+ if (NULL == factory) {
+ ALOGE("Failed to register MediaPlayerFactory of type %d, factory is"
+ " NULL.", type);
+ return BAD_VALUE;
+ }
+
+ if (sFactoryMap.indexOfKey(type) >= 0) {
+ ALOGE("Failed to register MediaPlayerFactory of type %d, type is"
+ " already registered.", type);
+ return ALREADY_EXISTS;
+ }
+
+ if (sFactoryMap.add(type, factory) < 0) {
+ ALOGE("Failed to register MediaPlayerFactory of type %d, failed to add"
+ " to map.", type);
+ return UNKNOWN_ERROR;
+ }
+
+ return OK;
+}
+
+player_type MediaPlayerFactory::getDefaultPlayerType() {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.stagefright.use-nuplayer", value, NULL)
+ && (!strcmp("1", value) || !strcasecmp("true", value))) {
+ return NU_PLAYER;
+ }
+
+ return STAGEFRIGHT_PLAYER;
+}
+
+status_t MediaPlayerFactory::registerFactory(IFactory* factory,
+ player_type type) {
+ Mutex::Autolock lock_(&sLock);
+ return registerFactory_l(factory, type);
+}
+
+void MediaPlayerFactory::unregisterFactory(player_type type) {
+ Mutex::Autolock lock_(&sLock);
+ sFactoryMap.removeItem(type);
+}
+
+#define GET_PLAYER_TYPE_IMPL(a...) \
+ Mutex::Autolock lock_(&sLock); \
+ \
+ player_type ret = STAGEFRIGHT_PLAYER; \
+ float bestScore = 0.0; \
+ \
+ for (size_t i = 0; i < sFactoryMap.size(); ++i) { \
+ \
+ IFactory* v = sFactoryMap.valueAt(i); \
+ float thisScore; \
+ CHECK(v != NULL); \
+ thisScore = v->scoreFactory(a, bestScore); \
+ if (thisScore > bestScore) { \
+ ret = sFactoryMap.keyAt(i); \
+ bestScore = thisScore; \
+ } \
+ } \
+ \
+ if (0.0 == bestScore) { \
+ bestScore = getDefaultPlayerType(); \
+ } \
+ \
+ return ret;
+
+player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
+ const char* url) {
+ GET_PLAYER_TYPE_IMPL(client, url);
+}
+
+player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
+ int fd,
+ int64_t offset,
+ int64_t length) {
+ GET_PLAYER_TYPE_IMPL(client, fd, offset, length);
+}
+
+player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client,
+ const sp<IStreamSource> &source) {
+ GET_PLAYER_TYPE_IMPL(client, source);
+}
+
+#undef GET_PLAYER_TYPE_IMPL
+
+sp<MediaPlayerBase> MediaPlayerFactory::createPlayer(
+ player_type playerType,
+ void* cookie,
+ notify_callback_f notifyFunc) {
+ sp<MediaPlayerBase> p;
+ IFactory* factory;
+ status_t init_result;
+ Mutex::Autolock lock_(&sLock);
+
+ if (sFactoryMap.indexOfKey(playerType) < 0) {
+ ALOGE("Failed to create player object of type %d, no registered"
+ " factory", playerType);
+ return p;
+ }
+
+ factory = sFactoryMap.valueFor(playerType);
+ CHECK(NULL != factory);
+ p = factory->createPlayer();
+
+ if (p == NULL) {
+ ALOGE("Failed to create player object of type %d, create failed",
+ playerType);
+ return p;
+ }
+
+ init_result = p->initCheck();
+ if (init_result == NO_ERROR) {
+ p->setNotifyCallback(cookie, notifyFunc);
+ } else {
+ ALOGE("Failed to create player object of type %d, initCheck failed"
+ " (res = %d)", playerType, init_result);
+ p.clear();
+ }
+
+ return p;
+}
+
+/*****************************************************************************
+ * *
+ * Built-In Factory Implementations *
+ * *
+ *****************************************************************************/
+
+class StagefrightPlayerFactory :
+ public MediaPlayerFactory::IFactory {
+ public:
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ int fd,
+ int64_t offset,
+ int64_t length,
+ float curScore) {
+ char buf[20];
+ lseek(fd, offset, SEEK_SET);
+ read(fd, buf, sizeof(buf));
+ lseek(fd, offset, SEEK_SET);
+
+ long ident = *((long*)buf);
+
+ // Ogg vorbis?
+ if (ident == 0x5367674f) // 'OggS'
+ return 1.0;
+
+ return 0.0;
+ }
+
+ virtual sp<MediaPlayerBase> createPlayer() {
+ ALOGV(" create StagefrightPlayer");
+ return new StagefrightPlayer();
+ }
+};
+
+class NuPlayerFactory : public MediaPlayerFactory::IFactory {
+ public:
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const char* url,
+ float curScore) {
+ static const float kOurScore = 0.8;
+
+ if (kOurScore <= curScore)
+ return 0.0;
+
+ if (!strncasecmp("http://", url, 7)
+ || !strncasecmp("https://", url, 8)) {
+ size_t len = strlen(url);
+ if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+ return kOurScore;
+ }
+
+ if (strstr(url,"m3u8")) {
+ return kOurScore;
+ }
+ }
+
+ if (!strncasecmp("rtsp://", url, 7)) {
+ return kOurScore;
+ }
+
+ return 0.0;
+ }
+
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const sp<IStreamSource> &source,
+ float curScore) {
+ return 1.0;
+ }
+
+ virtual sp<MediaPlayerBase> createPlayer() {
+ ALOGV(" create NuPlayer");
+ return new NuPlayerDriver;
+ }
+};
+
+class SonivoxPlayerFactory : public MediaPlayerFactory::IFactory {
+ public:
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const char* url,
+ float curScore) {
+ static const float kOurScore = 0.4;
+ static const char* const FILE_EXTS[] = { ".mid",
+ ".midi",
+ ".smf",
+ ".xmf",
+ ".imy",
+ ".rtttl",
+ ".rtx",
+ ".ota" };
+ if (kOurScore <= curScore)
+ return 0.0;
+
+ // use MidiFile for MIDI extensions
+ int lenURL = strlen(url);
+ for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
+ int len = strlen(FILE_EXTS[i]);
+ int start = lenURL - len;
+ if (start > 0) {
+ if (!strncasecmp(url + start, FILE_EXTS[i], len)) {
+ return kOurScore;
+ }
+ }
+ }
+
+ return 0.0;
+ }
+
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ int fd,
+ int64_t offset,
+ int64_t length,
+ float curScore) {
+ static const float kOurScore = 0.8;
+
+ if (kOurScore <= curScore)
+ return 0.0;
+
+ // Some kind of MIDI?
+ EAS_DATA_HANDLE easdata;
+ if (EAS_Init(&easdata) == EAS_SUCCESS) {
+ EAS_FILE locator;
+ locator.path = NULL;
+ locator.fd = fd;
+ locator.offset = offset;
+ locator.length = length;
+ EAS_HANDLE eashandle;
+ if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
+ EAS_CloseFile(easdata, eashandle);
+ EAS_Shutdown(easdata);
+ return kOurScore;
+ }
+ EAS_Shutdown(easdata);
+ }
+
+ return 0.0;
+ }
+
+ virtual sp<MediaPlayerBase> createPlayer() {
+ ALOGV(" create MidiFile");
+ return new MidiFile();
+ }
+};
+
+class TestPlayerFactory : public MediaPlayerFactory::IFactory {
+ public:
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const char* url,
+ float curScore) {
+ if (TestPlayerStub::canBeUsed(url)) {
+ return 1.0;
+ }
+
+ return 0.0;
+ }
+
+ virtual sp<MediaPlayerBase> createPlayer() {
+ ALOGV("Create Test Player stub");
+ return new TestPlayerStub();
+ }
+};
+
+class AAH_RX_PlayerFactory : public MediaPlayerFactory::IFactory {
+ public:
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const char* url,
+ float curScore) {
+ static const float kOurScore = 0.6;
+
+ if (kOurScore <= curScore)
+ return 0.0;
+
+ if (!strncasecmp("aahRX://", url, 8)) {
+ return kOurScore;
+ }
+
+ return 0.0;
+ }
+
+ virtual sp<MediaPlayerBase> createPlayer() {
+ ALOGV(" create A@H RX Player");
+ return createAAH_RXPlayer();
+ }
+};
+
+class AAH_TX_PlayerFactory : public MediaPlayerFactory::IFactory {
+ public:
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const char* url,
+ float curScore) {
+ return checkRetransmitEndpoint(client) ? 1.1 : 0.0;
+ }
+
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ int fd,
+ int64_t offset,
+ int64_t length,
+ float curScore) {
+ return checkRetransmitEndpoint(client) ? 1.1 : 0.0;
+ }
+
+ virtual sp<MediaPlayerBase> createPlayer() {
+ ALOGV(" create A@H TX Player");
+ return createAAH_TXPlayer();
+ }
+
+ private:
+ bool checkRetransmitEndpoint(const sp<IMediaPlayer>& client) {
+ if (client == NULL)
+ return false;
+
+ struct sockaddr_in junk;
+ if (OK != client->getRetransmitEndpoint(&junk))
+ return false;
+
+ return true;
+ }
+};
+
+void MediaPlayerFactory::registerBuiltinFactories() {
+ Mutex::Autolock lock_(&sLock);
+
+ if (sInitComplete)
+ return;
+
+ registerFactory_l(new StagefrightPlayerFactory(), STAGEFRIGHT_PLAYER);
+ registerFactory_l(new NuPlayerFactory(), NU_PLAYER);
+ registerFactory_l(new SonivoxPlayerFactory(), SONIVOX_PLAYER);
+ registerFactory_l(new TestPlayerFactory(), TEST_PLAYER);
+
+ // TODO: remove this once AAH players have been relocated from
+ // framework/base and into vendor/google_devices/phantasm
+ registerFactory_l(new AAH_RX_PlayerFactory(), AAH_RX_PLAYER);
+ registerFactory_l(new AAH_TX_PlayerFactory(), AAH_TX_PLAYER);
+
+ sInitComplete = true;
+}
+
+} // namespace android
diff --git a/media/libmediaplayerservice/MediaPlayerFactory.h b/media/libmediaplayerservice/MediaPlayerFactory.h
new file mode 100644
index 0000000..fe8972b
--- /dev/null
+++ b/media/libmediaplayerservice/MediaPlayerFactory.h
@@ -0,0 +1,84 @@
+/*
+**
+** Copyright 2012, 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.
+*/
+
+#ifndef ANDROID_MEDIAPLAYERFACTORY_H
+#define ANDROID_MEDIAPLAYERFACTORY_H
+
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace android {
+
+class MediaPlayerFactory {
+ public:
+ class IFactory {
+ public:
+ virtual ~IFactory() { }
+
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const char* url,
+ float curScore) { return 0.0; }
+
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ int fd,
+ int64_t offset,
+ int64_t length,
+ float curScore) { return 0.0; }
+
+ virtual float scoreFactory(const sp<IMediaPlayer>& client,
+ const sp<IStreamSource> &source,
+ float curScore) { return 0.0; }
+
+ virtual sp<MediaPlayerBase> createPlayer() = 0;
+ };
+
+ static status_t registerFactory(IFactory* factory,
+ player_type type);
+ static void unregisterFactory(player_type type);
+ static player_type getPlayerType(const sp<IMediaPlayer>& client,
+ const char* url);
+ static player_type getPlayerType(const sp<IMediaPlayer>& client,
+ int fd,
+ int64_t offset,
+ int64_t length);
+ static player_type getPlayerType(const sp<IMediaPlayer>& client,
+ const sp<IStreamSource> &source);
+
+ static sp<MediaPlayerBase> createPlayer(player_type playerType,
+ void* cookie,
+ notify_callback_f notifyFunc);
+
+ static void registerBuiltinFactories();
+
+ private:
+ typedef KeyedVector<player_type, IFactory*> tFactoryMap;
+
+ MediaPlayerFactory() { }
+
+ static status_t registerFactory_l(IFactory* factory,
+ player_type type);
+ static player_type getDefaultPlayerType();
+
+ static Mutex sLock;
+ static tFactoryMap sFactoryMap;
+ static bool sInitComplete;
+
+ DISALLOW_EVIL_CONSTRUCTORS(MediaPlayerFactory);
+};
+
+} // namespace android
+#endif // ANDROID_MEDIAPLAYERFACTORY_H
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index c47fbd6..8620856 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -43,7 +43,6 @@
#include <utils/String8.h>
#include <utils/SystemClock.h>
#include <utils/Vector.h>
-#include <cutils/properties.h>
#include <media/MediaPlayerInterface.h>
#include <media/mediarecorder.h>
@@ -61,6 +60,7 @@
#include "MediaRecorderClient.h"
#include "MediaPlayerService.h"
#include "MetadataRetrieverClient.h"
+#include "MediaPlayerFactory.h"
#include "MidiFile.h"
#include "TestPlayerStub.h"
@@ -71,11 +71,6 @@
#include "Crypto.h"
-namespace android {
-sp<MediaPlayerBase> createAAH_TXPlayer();
-sp<MediaPlayerBase> createAAH_RXPlayer();
-}
-
namespace {
using android::media::Metadata;
using android::status_t;
@@ -194,22 +189,6 @@ static bool checkPermission(const char* permissionString) {
return ok;
}
-// TODO: Temp hack until we can register players
-typedef struct {
- const char *extension;
- const player_type playertype;
-} extmap;
-extmap FILE_EXTS [] = {
- {".mid", SONIVOX_PLAYER},
- {".midi", SONIVOX_PLAYER},
- {".smf", SONIVOX_PLAYER},
- {".xmf", SONIVOX_PLAYER},
- {".imy", SONIVOX_PLAYER},
- {".rtttl", SONIVOX_PLAYER},
- {".rtx", SONIVOX_PLAYER},
- {".ota", SONIVOX_PLAYER},
-};
-
// TODO: Find real cause of Audio/Video delay in PV framework and remove this workaround
/* static */ int MediaPlayerService::AudioOutput::mMinBufferCount = 4;
/* static */ bool MediaPlayerService::AudioOutput::mIsOnEmulator = false;
@@ -232,6 +211,8 @@ MediaPlayerService::MediaPlayerService()
}
// speaker is on by default
mBatteryAudio.deviceOn[SPEAKER] = 1;
+
+ MediaPlayerFactory::registerBuiltinFactories();
}
MediaPlayerService::~MediaPlayerService()
@@ -545,174 +526,6 @@ void MediaPlayerService::Client::disconnect()
IPCThreadState::self()->flushCommands();
}
-static player_type getDefaultPlayerType() {
- char value[PROPERTY_VALUE_MAX];
- if (property_get("media.stagefright.use-nuplayer", value, NULL)
- && (!strcmp("1", value) || !strcasecmp("true", value))) {
- return NU_PLAYER;
- }
-
- return STAGEFRIGHT_PLAYER;
-}
-
-player_type getPlayerType(int fd, int64_t offset, int64_t length)
-{
- char buf[20];
- lseek(fd, offset, SEEK_SET);
- read(fd, buf, sizeof(buf));
- lseek(fd, offset, SEEK_SET);
-
- long ident = *((long*)buf);
-
- // Ogg vorbis?
- if (ident == 0x5367674f) // 'OggS'
- return STAGEFRIGHT_PLAYER;
-
- // Some kind of MIDI?
- EAS_DATA_HANDLE easdata;
- if (EAS_Init(&easdata) == EAS_SUCCESS) {
- EAS_FILE locator;
- locator.path = NULL;
- locator.fd = fd;
- locator.offset = offset;
- locator.length = length;
- EAS_HANDLE eashandle;
- if (EAS_OpenFile(easdata, &locator, &eashandle) == EAS_SUCCESS) {
- EAS_CloseFile(easdata, eashandle);
- EAS_Shutdown(easdata);
- return SONIVOX_PLAYER;
- }
- EAS_Shutdown(easdata);
- }
-
- return getDefaultPlayerType();
-}
-
-player_type getPlayerType(const char* url)
-{
- if (TestPlayerStub::canBeUsed(url)) {
- return TEST_PLAYER;
- }
-
- if (!strncasecmp("http://", url, 7)
- || !strncasecmp("https://", url, 8)) {
- size_t len = strlen(url);
- if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
- return NU_PLAYER;
- }
-
- if (strstr(url,"m3u8")) {
- return NU_PLAYER;
- }
- }
-
- if (!strncasecmp("rtsp://", url, 7)) {
- return NU_PLAYER;
- }
-
- if (!strncasecmp("aahRX://", url, 8)) {
- return AAH_RX_PLAYER;
- }
-
- // use MidiFile for MIDI extensions
- int lenURL = strlen(url);
- for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
- int len = strlen(FILE_EXTS[i].extension);
- int start = lenURL - len;
- if (start > 0) {
- if (!strncasecmp(url + start, FILE_EXTS[i].extension, len)) {
- return FILE_EXTS[i].playertype;
- }
- }
- }
-
- return getDefaultPlayerType();
-}
-
-player_type MediaPlayerService::Client::getPlayerType(int fd,
- int64_t offset,
- int64_t length)
-{
- // Until re-transmit functionality is added to the existing core android
- // players, we use the special AAH TX player whenever we were configured
- // for retransmission.
- if (mRetransmitEndpointValid) {
- return AAH_TX_PLAYER;
- }
-
- return android::getPlayerType(fd, offset, length);
-}
-
-player_type MediaPlayerService::Client::getPlayerType(const char* url)
-{
- // Until re-transmit functionality is added to the existing core android
- // players, we use the special AAH TX player whenever we were configured
- // for retransmission.
- if (mRetransmitEndpointValid) {
- return AAH_TX_PLAYER;
- }
-
- return android::getPlayerType(url);
-}
-
-player_type MediaPlayerService::Client::getPlayerType(
- const sp<IStreamSource> &source) {
- // Until re-transmit functionality is added to the existing core android
- // players, we use the special AAH TX player whenever we were configured
- // for retransmission.
- if (mRetransmitEndpointValid) {
- return AAH_TX_PLAYER;
- }
-
- return NU_PLAYER;
-}
-
-static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie,
- notify_callback_f notifyFunc)
-{
- sp<MediaPlayerBase> p;
- switch (playerType) {
- case SONIVOX_PLAYER:
- ALOGV(" create MidiFile");
- p = new MidiFile();
- break;
- case STAGEFRIGHT_PLAYER:
- ALOGV(" create StagefrightPlayer");
- p = new StagefrightPlayer;
- break;
- case NU_PLAYER:
- ALOGV(" create NuPlayer");
- p = new NuPlayerDriver;
- break;
- case TEST_PLAYER:
- ALOGV("Create Test Player stub");
- p = new TestPlayerStub();
- break;
- case AAH_RX_PLAYER:
- ALOGV(" create A@H RX Player");
- p = createAAH_RXPlayer();
- break;
- case AAH_TX_PLAYER:
- ALOGV(" create A@H TX Player");
- p = createAAH_TXPlayer();
- break;
- default:
- ALOGE("Unknown player type: %d", playerType);
- return NULL;
- }
- if (p != NULL) {
- if (p->initCheck() == NO_ERROR) {
- p->setNotifyCallback(cookie, notifyFunc);
- } else {
- p.clear();
- }
- }
- if (p == NULL) {
- ALOGE("Failed to create player object");
- }
- return p;
-}
-
sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerType)
{
// determine if we have the right player type
@@ -722,7 +535,7 @@ sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerT
p.clear();
}
if (p == NULL) {
- p = android::createPlayer(playerType, this, notify);
+ p = MediaPlayerFactory::createPlayer(playerType, this, notify);
}
if (p != NULL) {
@@ -805,7 +618,7 @@ status_t MediaPlayerService::Client::setDataSource(
close(fd);
return mStatus;
} else {
- player_type playerType = getPlayerType(url);
+ player_type playerType = MediaPlayerFactory::getPlayerType(this, url);
sp<MediaPlayerBase> p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
@@ -842,10 +655,10 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64
ALOGV("calculated length = %lld", length);
}
- // Until re-transmit functionality is added to the existing core android
- // players, we use the special AAH TX player whenever we were configured for
- // retransmission.
- player_type playerType = getPlayerType(fd, offset, length);
+ player_type playerType = MediaPlayerFactory::getPlayerType(this,
+ fd,
+ offset,
+ length);
sp<MediaPlayerBase> p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
@@ -859,10 +672,7 @@ status_t MediaPlayerService::Client::setDataSource(int fd, int64_t offset, int64
status_t MediaPlayerService::Client::setDataSource(
const sp<IStreamSource> &source) {
// create the right type of player
- // Until re-transmit functionality is added to the existing core android
- // players, we use the special AAH TX player whenever we were configured for
- // retransmission.
- player_type playerType = getPlayerType(source);
+ player_type playerType = MediaPlayerFactory::getPlayerType(this, source);
sp<MediaPlayerBase> p = setDataSource_pre(playerType);
if (p == NULL) {
return NO_INIT;
@@ -1209,6 +1019,25 @@ status_t MediaPlayerService::Client::setRetransmitEndpoint(
return NO_ERROR;
}
+status_t MediaPlayerService::Client::getRetransmitEndpoint(
+ struct sockaddr_in* endpoint)
+{
+ if (NULL == endpoint)
+ return BAD_VALUE;
+
+ sp<MediaPlayerBase> p = getPlayer();
+
+ if (p != NULL)
+ return p->getRetransmitEndpoint(endpoint);
+
+ if (!mRetransmitEndpointValid)
+ return NO_INIT;
+
+ *endpoint = mRetransmitEndpoint;
+
+ return NO_ERROR;
+}
+
void MediaPlayerService::Client::notify(
void* cookie, int msg, int ext1, int ext2, const Parcel *obj)
{
@@ -1315,12 +1144,13 @@ sp<IMemory> MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, i
return mem;
}
- player_type playerType = getPlayerType(url);
+ player_type playerType =
+ MediaPlayerFactory::getPlayerType(NULL /* client */, url);
ALOGV("player type = %d", playerType);
// create the right type of player
sp<AudioCache> cache = new AudioCache(url);
- player = android::createPlayer(playerType, cache.get(), cache->notify);
+ player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
if (player == NULL) goto Exit;
if (player->hardwareOutput()) goto Exit;
@@ -1362,12 +1192,15 @@ sp<IMemory> MediaPlayerService::decode(int fd, int64_t offset, int64_t length, u
sp<MemoryBase> mem;
sp<MediaPlayerBase> player;
- player_type playerType = getPlayerType(fd, offset, length);
+ player_type playerType = MediaPlayerFactory::getPlayerType(NULL /* client */,
+ fd,
+ offset,
+ length);
ALOGV("player type = %d", playerType);
// create the right type of player
sp<AudioCache> cache = new AudioCache("decode_fd");
- player = android::createPlayer(playerType, cache.get(), cache->notify);
+ player = MediaPlayerFactory::createPlayer(playerType, cache.get(), cache->notify);
if (player == NULL) goto Exit;
if (player->hardwareOutput()) goto Exit;
diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h
index 95b1b05..6ede9a4 100644
--- a/media/libmediaplayerservice/MediaPlayerService.h
+++ b/media/libmediaplayerservice/MediaPlayerService.h
@@ -299,7 +299,6 @@ public:
private:
class Client : public BnMediaPlayer {
-
// IMediaPlayer interface
virtual void disconnect();
virtual status_t setVideoSurfaceTexture(
@@ -326,6 +325,7 @@ private:
virtual status_t setParameter(int key, const Parcel &request);
virtual status_t getParameter(int key, Parcel *reply);
virtual status_t setRetransmitEndpoint(const struct sockaddr_in* endpoint);
+ virtual status_t getRetransmitEndpoint(struct sockaddr_in* endpoint);
virtual status_t setNextPlayer(const sp<IMediaPlayer>& player);
sp<MediaPlayerBase> createPlayer(player_type playerType);
@@ -342,10 +342,6 @@ private:
void setDataSource_post(const sp<MediaPlayerBase>& p,
status_t status);
- player_type getPlayerType(int fd, int64_t offset, int64_t length);
- player_type getPlayerType(const char* url);
- player_type getPlayerType(const sp<IStreamSource> &source);
-
static void notify(void* cookie, int msg,
int ext1, int ext2, const Parcel *obj);
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index e44031e..348957f 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -37,12 +37,10 @@
#include "MidiMetadataRetriever.h"
#include "MetadataRetrieverClient.h"
#include "StagefrightMetadataRetriever.h"
+#include "MediaPlayerFactory.h"
namespace android {
-extern player_type getPlayerType(const char* url);
-extern player_type getPlayerType(int fd, int64_t offset, int64_t length);
-
MetadataRetrieverClient::MetadataRetrieverClient(pid_t pid)
{
ALOGV("MetadataRetrieverClient constructor pid(%d)", pid);
@@ -115,7 +113,17 @@ status_t MetadataRetrieverClient::setDataSource(
if (url == NULL) {
return UNKNOWN_ERROR;
}
- player_type playerType = getPlayerType(url);
+
+ // When asking the MediaPlayerFactory subsystem to choose a media player for
+ // a given URL, a pointer to an outer IMediaPlayer can be passed to the
+ // factory system to be taken into consideration along with the URL. In the
+ // case of choosing an instance of a MediaPlayerBase for a
+ // MetadataRetrieverClient, there is no outer IMediaPlayer which will
+ // eventually encapsulate the result of this selection. In this case, just
+ // pass NULL to getPlayerType to indicate that there is no outer
+ // IMediaPlayer to consider during selection.
+ player_type playerType =
+ MediaPlayerFactory::getPlayerType(NULL /* client */, url);
ALOGV("player type = %d", playerType);
sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
if (p == NULL) return NO_INIT;
@@ -150,7 +158,11 @@ status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t
ALOGV("calculated length = %lld", length);
}
- player_type playerType = getPlayerType(fd, offset, length);
+ player_type playerType =
+ MediaPlayerFactory::getPlayerType(NULL /* client */,
+ fd,
+ offset,
+ length);
ALOGV("player type = %d", playerType);
sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
if (p == NULL) {