Skip to content

Commit

Permalink
Add basic metadata retrieval support for midi, ogg, etc.
Browse files Browse the repository at this point in the history
Bug 2050320
  • Loading branch information
James Dong committed Sep 8, 2009
1 parent 0b98c94 commit 392ff3b
Show file tree
Hide file tree
Showing 9 changed files with 368 additions and 13 deletions.
22 changes: 22 additions & 0 deletions include/media/MediaMetadataRetrieverInterface.h
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions include/media/mediametadataretriever.h
Expand Up @@ -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
{
Expand Down
2 changes: 2 additions & 0 deletions media/libmediaplayerservice/Android.mk
Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions media/libmediaplayerservice/MediaPlayerService.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
66 changes: 55 additions & 11 deletions media/libmediaplayerservice/MetadataRetrieverClient.cpp
Expand Up @@ -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);
Expand Down Expand Up @@ -90,18 +93,50 @@ 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);
Mutex::Autolock lock(mLock);
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)
Expand All @@ -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);
Expand All @@ -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;
}
Expand Down
91 changes: 91 additions & 0 deletions 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;
}

};

49 changes: 49 additions & 0 deletions 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

0 comments on commit 392ff3b

Please sign in to comment.