summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2009-09-06 14:29:45 -0700
committerJames Dong <jdong@google.com>2009-09-08 11:04:53 -0700
commit148c1a2a96774517407717b61e5bc9cb08be8806 (patch)
treec6c4a5aff75009eddb3f89dfe7ba5f4ed9f75d40
parente07db23c4935e47ecedfec7537ba95163e5836e5 (diff)
downloadframeworks_av-148c1a2a96774517407717b61e5bc9cb08be8806.zip
frameworks_av-148c1a2a96774517407717b61e5bc9cb08be8806.tar.gz
frameworks_av-148c1a2a96774517407717b61e5bc9cb08be8806.tar.bz2
Add basic metadata retrieval support for midi, ogg, etc.
Bug 2050320
-rw-r--r--include/media/MediaMetadataRetrieverInterface.h22
-rw-r--r--include/media/mediametadataretriever.h12
-rw-r--r--media/libmediaplayerservice/Android.mk2
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp4
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp66
-rw-r--r--media/libmediaplayerservice/MidiMetadataRetriever.cpp91
-rw-r--r--media/libmediaplayerservice/MidiMetadataRetriever.h49
-rw-r--r--media/libmediaplayerservice/VorbisMetadataRetriever.cpp86
-rw-r--r--media/libmediaplayerservice/VorbisMetadataRetriever.h49
9 files changed, 368 insertions, 13 deletions
diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h
index b178836..e228357 100644
--- a/include/media/MediaMetadataRetrieverInterface.h
+++ b/include/media/MediaMetadataRetrieverInterface.h
@@ -44,6 +44,28 @@ class MediaMetadataRetrieverInterface : public MediaMetadataRetrieverBase
{
public:
virtual ~MediaMetadataRetrieverInterface() {}
+
+ // @param mode The intended mode of operations:
+ // can be any of the following:
+ // METADATA_MODE_NOOP: Experimental - just add and remove data source.
+ // METADATA_MODE_FRAME_CAPTURE_ONLY: For capture frame/thumbnail only.
+ // METADATA_MODE_METADATA_RETRIEVAL_ONLY: For meta data retrieval only.
+ // METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL: For both frame
+ // capture and meta data retrieval.
+ virtual status_t setMode(int mode) {
+ if (mode < METADATA_MODE_NOOP ||
+ mode > METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL) {
+ return BAD_VALUE;
+ }
+ return NO_ERROR;
+ }
+
+ virtual status_t getMode(int* mode) const { *mode = mMode; return NO_ERROR; }
+ virtual VideoFrame* captureFrame() { return NULL; }
+ virtual MediaAlbumArt* extractAlbumArt() { return NULL; }
+ virtual const char* extractMetadata(int keyCode) { return NULL; }
+
+ uint32_t mMode;
};
}; // namespace android
diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h
index 9ea2775..cfc205c 100644
--- a/include/media/mediametadataretriever.h
+++ b/include/media/mediametadataretriever.h
@@ -56,6 +56,18 @@ enum {
// Add more here...
};
+// The intended mode of operations:$
+// METADATA_MODE_NOOP: Experimental - just add and remove data source.$
+// METADATA_MODE_FRAME_CAPTURE_ONLY: For capture frame/thumbnail only.$
+// METADATA_MODE_METADATA_RETRIEVAL_ONLY: For meta data retrieval only.$
+// METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL: For both frame capture
+// and meta data retrieval.$
+enum {
+ METADATA_MODE_NOOP = 0x00,
+ METADATA_MODE_FRAME_CAPTURE_ONLY = 0x01,
+ METADATA_MODE_METADATA_RETRIEVAL_ONLY = 0x02,
+ METADATA_MODE_FRAME_CAPTURE_AND_METADATA_RETRIEVAL = 0x03
+};
class MediaMetadataRetriever: public RefBase
{
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk
index 84f858c..59ecde6 100644
--- a/media/libmediaplayerservice/Android.mk
+++ b/media/libmediaplayerservice/Android.mk
@@ -13,6 +13,8 @@ LOCAL_SRC_FILES:= \
StagefrightPlayer.cpp \
TestPlayerStub.cpp \
VorbisPlayer.cpp \
+ VorbisMetadataRetriever.cpp \
+ MidiMetadataRetriever.cpp \
MidiFile.cpp
ifeq ($(TARGET_OS)-$(TARGET_SIMULATOR),linux-true)
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index eeb4e49..8998f10 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -611,7 +611,7 @@ static player_type getDefaultPlayerType() {
return PV_PLAYER;
}
-static player_type getPlayerType(int fd, int64_t offset, int64_t length)
+player_type getPlayerType(int fd, int64_t offset, int64_t length)
{
char buf[20];
lseek(fd, offset, SEEK_SET);
@@ -644,7 +644,7 @@ static player_type getPlayerType(int fd, int64_t offset, int64_t length)
return getDefaultPlayerType();
}
-static player_type getPlayerType(const char* url)
+player_type getPlayerType(const char* url)
{
if (TestPlayerStub::canBeUsed(url)) {
return TEST_PLAYER;
diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
index ba8d9a8..b34421d 100644
--- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp
+++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp
@@ -34,12 +34,15 @@
#include <media/MediaPlayerInterface.h>
#include <media/PVMetadataRetriever.h>
#include <private/media/VideoFrame.h>
-
+#include "VorbisMetadataRetriever.h"
+#include "MidiMetadataRetriever.h"
#include "MetadataRetrieverClient.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)
{
LOGV("MetadataRetrieverClient constructor pid(%d)", pid);
@@ -90,6 +93,36 @@ void MetadataRetrieverClient::disconnect()
IPCThreadState::self()->flushCommands();
}
+static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType)
+{
+ sp<MediaMetadataRetrieverBase> p;
+ switch (playerType) {
+#ifndef NO_OPENCORE
+ case PV_PLAYER:
+ LOGV("create pv metadata retriever");
+ p = new PVMetadataRetriever();
+ break;
+#endif
+ case VORBIS_PLAYER:
+ LOGV("create vorbis metadata retriever");
+ p = new VorbisMetadataRetriever();
+ break;
+ case SONIVOX_PLAYER:
+ LOGV("create midi metadata retriever");
+ p = new MidiMetadataRetriever();
+ break;
+ default:
+ // TODO:
+ // support for STAGEFRIGHT_PLAYER and TEST_PLAYER
+ LOGE("player type %d is not supported", playerType);
+ break;
+ }
+ if (p == NULL) {
+ LOGE("failed to create a retriever object");
+ }
+ return p;
+}
+
status_t MetadataRetrieverClient::setDataSource(const char *url)
{
LOGV("setDataSource(%s)", url);
@@ -97,11 +130,13 @@ status_t MetadataRetrieverClient::setDataSource(const char *url)
if (url == NULL) {
return UNKNOWN_ERROR;
}
- if (mRetriever == NULL) {
- LOGE("retriever is not initialized");
- return NO_INIT;
- }
- return mRetriever->setDataSource(url);
+ player_type playerType = getPlayerType(url);
+ LOGV("player type = %d", playerType);
+ sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
+ if (p == NULL) return NO_INIT;
+ status_t ret = p->setDataSource(url);
+ if (ret == NO_ERROR) mRetriever = p;
+ return ret;
}
status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t length)
@@ -118,7 +153,7 @@ status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t
int ret = fstat(fd, &sb);
if (ret != 0) {
LOGE("fstat(%d) failed: %d, %s", fd, ret, strerror(errno));
- return UNKNOWN_ERROR;
+ return BAD_VALUE;
}
LOGV("st_dev = %llu", sb.st_dev);
LOGV("st_mode = %u", sb.st_mode);
@@ -129,13 +164,22 @@ status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t
if (offset >= sb.st_size) {
LOGE("offset (%lld) bigger than file size (%llu)", offset, sb.st_size);
::close(fd);
- return UNKNOWN_ERROR;
+ return BAD_VALUE;
}
if (offset + length > sb.st_size) {
length = sb.st_size - offset;
- LOGE("calculated length = %lld", length);
+ LOGV("calculated length = %lld", length);
+ }
+
+ player_type playerType = getPlayerType(fd, offset, length);
+ LOGV("player type = %d", playerType);
+ sp<MediaMetadataRetrieverBase> p = createRetriever(playerType);
+ if (p == NULL) {
+ ::close(fd);
+ return NO_INIT;
}
- status_t status = mRetriever->setDataSource(fd, offset, length);
+ status_t status = p->setDataSource(fd, offset, length);
+ if (status == NO_ERROR) mRetriever = p;
::close(fd);
return status;
}
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
new file mode 100644
index 0000000..3795b7b
--- /dev/null
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.cpp
@@ -0,0 +1,91 @@
+/*
+**
+** Copyright 2009, 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_NDEBUG 0
+#define LOG_TAG "MidiMetadataRetriever"
+#include <utils/Log.h>
+
+#include "MidiMetadataRetriever.h"
+#include <media/mediametadataretriever.h>
+
+namespace android {
+
+static status_t ERROR_NOT_OPEN = -1;
+static status_t ERROR_OPEN_FAILED = -2;
+static status_t ERROR_EAS_FAILURE = -3;
+static status_t ERROR_ALLOCATE_FAILED = -4;
+
+void MidiMetadataRetriever::clearMetadataValues()
+{
+ LOGV("clearMetadataValues");
+ mMetadataValues[0][0] = '\0';
+}
+
+status_t MidiMetadataRetriever::setDataSource(const char *url)
+{
+ LOGV("setDataSource: %s", url? url: "NULL pointer");
+ Mutex::Autolock lock(mLock);
+ clearMetadataValues();
+ if (mMidiPlayer == 0) {
+ mMidiPlayer = new MidiFile();
+ }
+ return mMidiPlayer->setDataSource(url);
+}
+
+status_t MidiMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ LOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
+ Mutex::Autolock lock(mLock);
+ clearMetadataValues();
+ if (mMidiPlayer == 0) {
+ mMidiPlayer = new MidiFile();
+ }
+ return mMidiPlayer->setDataSource(fd, offset, length);;
+}
+
+const char* MidiMetadataRetriever::extractMetadata(int keyCode)
+{
+ LOGV("extractMetdata: key(%d)", keyCode);
+ Mutex::Autolock lock(mLock);
+ if (mMidiPlayer == 0 || mMidiPlayer->initCheck() != NO_ERROR) {
+ LOGE("Midi player is not initialized yet");
+ return NULL;
+ }
+ switch (keyCode) {
+ case METADATA_KEY_DURATION:
+ {
+ if (mMetadataValues[0][0] == '\0') {
+ int duration = -1;
+ if (mMidiPlayer->getDuration(&duration) != NO_ERROR) {
+ LOGE("failed to get duration");
+ return NULL;
+ }
+ snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
+ }
+
+ LOGV("duration: %s ms", mMetadataValues[0]);
+ return mMetadataValues[0];
+ }
+ default:
+ LOGE("Unsupported key code (%d)", keyCode);
+ return NULL;
+ }
+ return NULL;
+}
+
+};
+
diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.h b/media/libmediaplayerservice/MidiMetadataRetriever.h
new file mode 100644
index 0000000..73ff347
--- /dev/null
+++ b/media/libmediaplayerservice/MidiMetadataRetriever.h
@@ -0,0 +1,49 @@
+/*
+**
+** Copyright 2009, 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_MIDIMETADATARETRIEVER_H
+#define ANDROID_MIDIMETADATARETRIEVER_H
+
+#include <utils/threads.h>
+#include <utils/Errors.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+
+#include "MidiFile.h"
+
+namespace android {
+
+class MidiMetadataRetriever : public MediaMetadataRetrieverInterface {
+public:
+ MidiMetadataRetriever() {}
+ ~MidiMetadataRetriever() {}
+
+ virtual status_t setDataSource(const char *url);
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual const char* extractMetadata(int keyCode);
+
+private:
+ static const uint32_t MAX_METADATA_STRING_LENGTH = 128;
+ void clearMetadataValues();
+
+ Mutex mLock;
+ sp<MidiFile> mMidiPlayer;
+ char mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
+};
+
+}; // namespace android
+
+#endif // ANDROID_MIDIMETADATARETRIEVER_H
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
new file mode 100644
index 0000000..e981678
--- /dev/null
+++ b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp
@@ -0,0 +1,86 @@
+/*
+**
+** Copyright 2009, 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_NDEBUG 0
+#define LOG_TAG "VorbisMetadataRetriever"
+#include <utils/Log.h>
+
+#include "VorbisMetadataRetriever.h"
+#include <media/mediametadataretriever.h>
+#
+
+namespace android {
+
+void VorbisMetadataRetriever::clearMetadataValues()
+{
+ LOGV("cleearMetadataValues");
+ mMetadataValues[0][0] = '\0';
+}
+
+status_t VorbisMetadataRetriever::setDataSource(const char *url)
+{
+ LOGV("setDataSource: url(%s)", url? url: "NULL pointer");
+ Mutex::Autolock lock(mLock);
+ clearMetadataValues();
+ if (mVorbisPlayer == 0) {
+ mVorbisPlayer = new VorbisPlayer();
+ }
+ return mVorbisPlayer->setDataSource(url);
+}
+
+status_t VorbisMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length)
+{
+ LOGV("setDataSource: fd(%d), offset(%lld), and length(%lld)", fd, offset, length);
+ Mutex::Autolock lock(mLock);
+ clearMetadataValues();
+ if (mVorbisPlayer == 0) {
+ mVorbisPlayer = new VorbisPlayer();
+ }
+ return mVorbisPlayer->setDataSource(fd, offset, length);
+}
+
+const char* VorbisMetadataRetriever::extractMetadata(int keyCode)
+{
+ LOGV("extractMetadata: key(%d)", keyCode);
+ Mutex::Autolock lock(mLock);
+ if (mVorbisPlayer == 0 || mVorbisPlayer->initCheck() != NO_ERROR) {
+ LOGE("no vorbis player is initialized yet");
+ return NULL;
+ }
+ switch (keyCode) {
+ case METADATA_KEY_DURATION:
+ {
+ if (mMetadataValues[0][0] == '\0') {
+ int duration = -1;
+ if (mVorbisPlayer->getDuration(&duration) != NO_ERROR) {
+ LOGE("failed to get duration");
+ return NULL;
+ }
+ snprintf(mMetadataValues[0], MAX_METADATA_STRING_LENGTH, "%d", duration);
+ }
+ LOGV("duration: %s ms", mMetadataValues[0]);
+ return mMetadataValues[0];
+ }
+ default:
+ LOGE("Unsupported key code (%d)", keyCode);
+ return NULL;
+ }
+ return NULL;
+}
+
+};
+
diff --git a/media/libmediaplayerservice/VorbisMetadataRetriever.h b/media/libmediaplayerservice/VorbisMetadataRetriever.h
new file mode 100644
index 0000000..1c57fe3
--- /dev/null
+++ b/media/libmediaplayerservice/VorbisMetadataRetriever.h
@@ -0,0 +1,49 @@
+/*
+**
+** Copyright 2009, 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_VORBISMETADATARETRIEVER_H
+#define ANDROID_VORBISMETADATARETRIEVER_H
+
+#include <utils/threads.h>
+#include <utils/Errors.h>
+#include <media/MediaMetadataRetrieverInterface.h>
+
+#include "VorbisPlayer.h"
+
+namespace android {
+
+class VorbisMetadataRetriever : public MediaMetadataRetrieverInterface {
+public:
+ VorbisMetadataRetriever() {}
+ ~VorbisMetadataRetriever() {}
+
+ virtual status_t setDataSource(const char *url);
+ virtual status_t setDataSource(int fd, int64_t offset, int64_t length);
+ virtual const char* extractMetadata(int keyCode);
+
+private:
+ static const uint32_t MAX_METADATA_STRING_LENGTH = 128;
+ void clearMetadataValues();
+
+ Mutex mLock;
+ sp<VorbisPlayer> mVorbisPlayer;
+ char mMetadataValues[1][MAX_METADATA_STRING_LENGTH];
+};
+
+}; // namespace android
+
+#endif // ANDROID_VORBISMETADATARETRIEVER_H